use std::mem;
use std::sync::Arc;

use cairo_lang_diagnostics::DiagnosticsBuilder;
use cairo_lang_filesystem::db::FilesGroup;
use cairo_lang_filesystem::ids::{FileId, SmolStrId};
use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth};
use cairo_lang_primitive_token::{PrimitiveToken, ToPrimitiveTokenStream};
use cairo_lang_syntax as syntax;
use cairo_lang_syntax::node::ast::*;
use cairo_lang_syntax::node::helpers::GetIdentifier;
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{SyntaxNode, Token, TypedSyntaxNode};
use cairo_lang_utils::deque::Deque;
use cairo_lang_utils::{extract_matches, require};
use salsa::Database;
use syntax::node::green::{GreenNode, GreenNodeDetails};
use syntax::node::ids::GreenId;

use crate::ParserDiagnostic;
use crate::diagnostic::ParserDiagnosticKind;
use crate::lexer::{LexerTerminal, tokenize_all};
use crate::operators::{get_post_operator_precedence, get_unary_operator_precedence};
use crate::recovery::is_of_kind;
use crate::utils::primitive_token_stream_content_and_offset;
use crate::validation::{
    ValidationError, ValidationLocation, validate_literal_number, validate_short_string,
    validate_string,
};

#[cfg(test)]
#[path = "parser_test.rs"]
mod test;

#[derive(PartialEq)]
enum MacroParsingContext {
    /// The code being parsed is a part of a macro rule.
    MacroRule,
    /// The code being parsed is a part of a macro expansion.
    MacroExpansion,
    /// The code being parsed was generated by a macro expansion.
    ExpandedMacro,
    /// None of the above.
    None,
}

pub struct Parser<'a, 'mt> {
    db: &'a dyn Database,
    file_id: FileId<'a>,
    /// A queue of lexed tokens to be parsed.
    terminals: Deque<LexerTerminal<'a>>,
    /// A vector of pending trivia to be added as leading trivia to the next valid terminal.
    pending_trivia: Vec<TriviumGreen<'a>>,
    /// The current offset, excluding the current terminal.
    offset: TextOffset,
    /// The width of the current terminal being handled (excluding the trivia length of this
    /// terminal).
    current_width: TextWidth,
    /// The length of the trailing trivia following the last read token.
    last_trivia_length: TextWidth,
    diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
    /// An accumulating vector of pending skipped tokens diagnostics.
    pending_skipped_token_diagnostics: Vec<PendingParserDiagnostic>,
    /// An indicator if we are inside a macro rule expansion.
    macro_parsing_context: MacroParsingContext,
}

impl<'a> Parser<'a, '_> {
    fn next_terminal(&self) -> &LexerTerminal<'a> {
        &self.terminals[0]
    }

    fn next_next_terminal(&self) -> &LexerTerminal<'a> {
        &self.terminals[1]
    }

    fn advance(&mut self) -> LexerTerminal<'a> {
        self.terminals.pop_front().unwrap()
    }

    fn next_terminal_mut(&mut self) -> &mut LexerTerminal<'a> {
        &mut self.terminals[0]
    }
}

/// The possible results of a try_parse_* function failing to parse.
#[derive(PartialEq, Debug)]
pub enum TryParseFailure {
    /// The parsing failed and no token was consumed. The current token is the one which caused
    /// the failure and thus should be skipped by the caller.
    SkipToken,
    /// The parsing failed, some tokens were consumed, and the current token is yet to be
    /// processed. Should be used when the failure cannot be
    /// determined by the first token alone, and thus the tokens until the token which
    /// determines the failure should be consumed.
    DoNothing,
}
/// The result of a try_parse_* function.
pub type TryParseResult<GreenElement> = Result<GreenElement, TryParseFailure>;

// ====================================== Naming of items ======================================
// To avoid confusion, there is a naming convention for the language items.
// An item is called <item_scope>Item<item_kind>, where item_scope is in {Module, Trait, Impl}, and
// item_kind is in {Const, Enum, ExternFunction, ExternType, Function, Impl, InlineMacro, Module,
// Struct, Trait, Type, TypeAlias, Use} (note that not all combinations are supported).
// For example, ModuleItemFunction is a function item in a module, TraitItemConst is a const item in
// a trait.

// ================================ Naming of parsing functions ================================
// try_parse_<something>: returns a TryParseResult. An `Ok` with a green ID with a kind
// that represents 'something' or an `Err` if 'something' can't be parsed.
// If the error kind is Failure, the current token is not consumed, otherwise (Success or
// error of kind FailureAndSkipped) it is (taken or skipped). Used when something may or may not be
// there and we can act differently according to each case.
//
// parse_option_<something>: returns a green ID with a kind that represents 'something'. If
// 'something' can't be parsed, returns a green ID with the relevant empty kind. Used for an
// optional child. Always returns some green ID.
//
// parse_<something>: returns a green ID with a kind that represents 'something'. If
// 'something' can't be parsed, returns a green ID with the relevant missing kind. Used when we
// expect 'something' to be there. Always returns some green ID.
//
// expect_<something>: similar to parse_<something>, but assumes the current token is as expected.
// Therefore, it always returns a GreenId of a node with a kind that represents 'something' and
// never returns a missing kind.
// Should only be called after checking the current token.

const MAX_PRECEDENCE: usize = 1000;
const MODULE_ITEM_DESCRIPTION: &str = "Const/Enum/ExternFunction/ExternType/Function/Impl/\
                                       InlineMacro/Module/Struct/Trait/TypeAlias/Use";
const TRAIT_ITEM_DESCRIPTION: &str = "Const/Function/Impl/Type";
const IMPL_ITEM_DESCRIPTION: &str = "Const/Function/Impl/Type";

// A macro adding "or an attribute" to the end of a string.
macro_rules! or_an_attribute {
    ($string:expr) => {
        format!("{} or an attribute", $string)
    };
}

impl<'a, 'mt> Parser<'a, 'mt> {
    /// Creates a new parser.
    pub fn new(
        db: &'a dyn Database,
        file_id: FileId<'a>,
        text: &'a str,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
    ) -> Self {
        let tokens: Deque<LexerTerminal<'a>> = tokenize_all(db, (), Arc::from(text));
        Parser {
            db,
            file_id,
            terminals: tokens,
            pending_trivia: Vec::new(),
            offset: Default::default(),
            current_width: Default::default(),
            last_trivia_length: Default::default(),
            diagnostics,
            pending_skipped_token_diagnostics: Vec::new(),
            macro_parsing_context: MacroParsingContext::None,
        }
    }

    /// Adds a diagnostic to the parser diagnostics collection.
    pub fn add_diagnostic(&mut self, kind: ParserDiagnosticKind, span: TextSpan) {
        self.diagnostics.add(ParserDiagnostic { file_id: self.file_id, kind, span });
    }

    /// Parses a file.
    pub fn parse_file(
        db: &'a dyn Database,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
        file_id: FileId<'a>,
        text: &'a str,
    ) -> SyntaxFile<'a> {
        let parser = Parser::new(db, file_id, text, diagnostics);
        let green = parser.parse_syntax_file();
        SyntaxFile::from_syntax_node(db, SyntaxNode::new_root(db, file_id, green.0))
    }

    /// Parses a file expr.
    pub fn parse_file_expr(
        db: &'a dyn Database,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
        file_id: FileId<'a>,
        text: &'a str,
    ) -> Expr<'a> {
        let mut parser = Parser::new(db, file_id, text, diagnostics);
        parser.macro_parsing_context = MacroParsingContext::ExpandedMacro;
        let green = parser.parse_expr();
        if let Err(SkippedError(span)) = parser.skip_until(is_of_kind!()) {
            parser.add_diagnostic(
                ParserDiagnosticKind::SkippedElement { element_name: "end of expr".into() },
                span,
            );
        }
        Expr::from_syntax_node(db, SyntaxNode::new_root(db, file_id, green.0))
    }

    /// Parses a file as a list of statements.
    pub fn parse_file_statement_list(
        db: &'a dyn Database,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
        file_id: FileId<'a>,
        text: &'a str,
    ) -> StatementList<'a> {
        let mut parser = Parser::new(db, file_id, text, diagnostics);
        parser.macro_parsing_context = MacroParsingContext::ExpandedMacro;
        let statements = StatementList::new_green(
            db,
            &parser.parse_list(Self::try_parse_statement, Self::is_eof, "statement"),
        );
        StatementList::from_syntax_node(db, SyntaxNode::new_root(db, file_id, statements.0))
    }

    /// Checks if the given kind is an end of file token.
    pub fn is_eof(kind: SyntaxKind) -> bool {
        kind == SyntaxKind::TerminalEndOfFile
    }

    /// Parses a token stream.
    pub fn parse_token_stream(
        db: &'a dyn Database,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
        file_id: FileId<'a>,
        token_stream: &dyn ToPrimitiveTokenStream<Iter = impl Iterator<Item = PrimitiveToken>>,
    ) -> SyntaxFile<'a> {
        let (content, offset) = primitive_token_stream_content_and_offset(token_stream);
        let file_content = db.file_content(file_id).unwrap();
        let file_content_at_offset = offset.unwrap_or_default().take_from(file_content);
        assert!(
            file_content_at_offset.starts_with(&content),
            "The content of the file at the offset is not the same as the content of the token \
             stream"
        );
        let content = &file_content_at_offset[..content.len()];
        let parser = Parser::new(db, file_id, content, diagnostics);
        let green = parser.parse_syntax_file();
        SyntaxFile::from_syntax_node(
            db,
            SyntaxNode::new_root_with_offset(db, file_id, green.0, offset),
        )
    }

    /// Parses a token stream expression.
    pub fn parse_token_stream_expr(
        db: &'a dyn Database,
        diagnostics: &'mt mut DiagnosticsBuilder<'a, ParserDiagnostic<'a>>,
        file_id: FileId<'a>,
        offset: Option<TextOffset>,
    ) -> Expr<'a> {
        let content = db.file_content(file_id).unwrap();
        let mut parser = Parser::new(db, file_id, content, diagnostics);
        let green = parser.parse_expr();
        if let Err(SkippedError(span)) = parser.skip_until(is_of_kind!()) {
            parser.diagnostics.add(ParserDiagnostic {
                file_id: parser.file_id,
                kind: ParserDiagnosticKind::SkippedElement { element_name: "end of expr".into() },
                span,
            });
        }
        Expr::from_syntax_node(db, SyntaxNode::new_root_with_offset(db, file_id, green.0, offset))
    }

    /// Returns a GreenId of an ExprMissing and adds a diagnostic describing it.
    fn create_and_report_missing<T: TypedSyntaxNode<'a>>(
        &mut self,
        missing_kind: ParserDiagnosticKind,
    ) -> T::Green {
        let next_offset = self.offset.add_width(self.current_width - self.last_trivia_length);
        self.add_diagnostic(missing_kind, TextSpan::cursor(next_offset));
        T::missing(self.db)
    }

    /// Returns the missing terminal and adds the corresponding missing token
    /// diagnostic report.
    fn create_and_report_missing_terminal<Terminal: syntax::node::Terminal<'a>>(
        &mut self,
    ) -> Terminal::Green {
        self.create_and_report_missing::<Terminal>(ParserDiagnosticKind::MissingToken(
            Terminal::KIND,
        ))
    }

    pub fn parse_syntax_file(mut self) -> SyntaxFileGreen<'a> {
        let mut module_items = vec![];
        if let Some(doc_item) = self.take_doc() {
            module_items.push(doc_item.into());
        }
        module_items.extend(self.parse_attributed_list(
            Self::try_parse_module_item,
            is_of_kind!(),
            MODULE_ITEM_DESCRIPTION,
        ));
        // Create a new vec with the doc item as the children.
        let items = ModuleItemList::new_green(self.db, &module_items);
        // This will not panic since the above parsing only stops when reaches EOF.
        assert_eq!(self.peek().kind, SyntaxKind::TerminalEndOfFile);

        // Fix offset in case there are skipped tokens before EOF. This is usually done in
        // self.take_raw() but here we don't call self.take_raw as it tries to read the next
        // token, which doesn't exist.
        self.offset = self.offset.add_width(self.current_width);

        let eof =
            self.add_trivia_to_terminal::<TerminalEndOfFile<'_>>(self.next_terminal().clone());
        SyntaxFile::new_green(self.db, items, eof)
    }

    // ------------------------------- Module items -------------------------------

    /// Returns a GreenId of a node with an Item.* kind (see [syntax::node::ast::ModuleItem]), or
    /// TryParseFailure if a module item can't be parsed.
    /// In case of an identifier not followed by a `!`, it is skipped inside the function and thus a
    /// TryParseFailure::DoNothing is returned.
    pub fn try_parse_module_item(&mut self) -> TryParseResult<ModuleItemGreen<'a>> {
        let maybe_attributes = self.try_parse_attribute_list(MODULE_ITEM_DESCRIPTION);
        let (has_attrs, attributes) = match maybe_attributes {
            Ok(attributes) => (true, attributes),
            Err(_) => (false, AttributeList::new_green(self.db, &[])),
        };
        let post_attributes_offset = self.offset.add_width(self.current_width);

        let visibility_pub = self.try_parse_visibility_pub();
        let visibility = match visibility_pub {
            Some(visibility) => visibility.into(),
            None => VisibilityDefault::new_green(self.db).into(),
        };
        let post_visibility_offset = self.offset.add_width(self.current_width);

        match self.peek().kind {
            SyntaxKind::TerminalConst => {
                let const_kw = self.take::<TerminalConst<'_>>();
                Ok(if self.peek().kind == SyntaxKind::TerminalFunction {
                    self.expect_item_function_with_body(attributes, visibility, const_kw.into())
                        .into()
                } else {
                    self.expect_item_const(attributes, visibility, const_kw).into()
                })
            }
            SyntaxKind::TerminalModule => {
                Ok(self.expect_item_module(attributes, visibility).into())
            }
            SyntaxKind::TerminalStruct => {
                Ok(self.expect_item_struct(attributes, visibility).into())
            }
            SyntaxKind::TerminalEnum => Ok(self.expect_item_enum(attributes, visibility).into()),
            SyntaxKind::TerminalType => {
                Ok(self.expect_item_type_alias(attributes, visibility).into())
            }
            SyntaxKind::TerminalExtern => Ok(self.expect_item_extern(attributes, visibility)),
            SyntaxKind::TerminalFunction => Ok(self
                .expect_item_function_with_body(
                    attributes,
                    visibility,
                    OptionTerminalConstEmpty::new_green(self.db).into(),
                )
                .into()),
            SyntaxKind::TerminalUse => Ok(self.expect_item_use(attributes, visibility).into()),
            SyntaxKind::TerminalTrait => Ok(self.expect_item_trait(attributes, visibility).into()),
            SyntaxKind::TerminalImpl => Ok(self.expect_module_item_impl(attributes, visibility)),
            SyntaxKind::TerminalMacro => {
                Ok(self.expect_item_macro_declaration(attributes, visibility).into())
            }
            SyntaxKind::TerminalIdentifier | SyntaxKind::TerminalDollar => {
                // We take the identifier to check if the next token is a `!`. If it is, we assume
                // that a macro is following and handle it similarly to any other module item. If
                // not we skip the identifier. 'take_raw' is used here since it is not yet known if
                // the identifier would be taken as a part of a macro, or skipped.
                let path = self.parse_path();
                let post_path_offset = self.offset.add_width(self.current_width);
                match self.peek().kind {
                    SyntaxKind::TerminalLParen
                    | SyntaxKind::TerminalLBrace
                    | SyntaxKind::TerminalLBrack => {
                        // This case is treated as an item inline macro with a missing bang ('!').
                        self.add_diagnostic(
                            ParserDiagnosticKind::ItemInlineMacroWithoutBang {
                                identifier: path.identifier(self.db).long(self.db).to_string(),
                                bracket_type: self.peek().kind,
                            },
                            TextSpan::new(self.offset, self.offset.add_width(self.current_width)),
                        );
                        Ok(self
                            .parse_item_inline_macro_given_bang(
                                attributes,
                                path,
                                TerminalNot::missing(self.db),
                            )
                            .into())
                    }
                    SyntaxKind::TerminalNot => {
                        Ok(self.expect_item_inline_macro(attributes, path).into())
                    }
                    _ => {
                        if has_attrs {
                            self.skip_taken_node_with_offset(
                                attributes,
                                ParserDiagnosticKind::SkippedElement {
                                    element_name: or_an_attribute!(MODULE_ITEM_DESCRIPTION),
                                },
                                post_attributes_offset,
                            );
                        }
                        if let Some(visibility_pub) = visibility_pub {
                            self.skip_taken_node_with_offset(
                                visibility_pub,
                                ParserDiagnosticKind::SkippedElement {
                                    element_name: or_an_attribute!(MODULE_ITEM_DESCRIPTION),
                                },
                                post_visibility_offset,
                            );
                        }
                        // TODO(Dean): This produces a slightly worse diagnostic than before.
                        self.skip_taken_node_with_offset(
                            path,
                            ParserDiagnosticKind::SkippedElement {
                                element_name: or_an_attribute!(MODULE_ITEM_DESCRIPTION),
                            },
                            post_path_offset,
                        );
                        // The token is already skipped, so it should not be skipped in the caller.
                        Err(TryParseFailure::DoNothing)
                    }
                }
            }
            _ => {
                let mut result = Err(TryParseFailure::SkipToken);
                if has_attrs {
                    self.skip_taken_node_with_offset(
                        attributes,
                        ParserDiagnosticKind::AttributesWithoutItem,
                        post_attributes_offset,
                    );
                    result = Ok(ModuleItem::missing(self.db));
                }
                if let Some(visibility_pub) = visibility_pub {
                    self.skip_taken_node_with_offset(
                        visibility_pub,
                        ParserDiagnosticKind::VisibilityWithoutItem,
                        post_visibility_offset,
                    );
                    result = Ok(ModuleItem::missing(self.db));
                }
                result
            }
        }
    }

    /// Assumes the current token is Module.
    /// Expected pattern: `mod <Identifier> \{<ItemList>\}` or `mod <Identifier>;`.
    fn expect_item_module(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemModuleGreen<'a> {
        let module_kw = self.take::<TerminalModule<'_>>();
        let name = self.parse_identifier();

        let body = match self.peek().kind {
            SyntaxKind::TerminalLBrace => {
                let lbrace = self.take::<TerminalLBrace<'_>>();
                let mut module_items = vec![];
                if let Some(doc_item) = self.take_doc() {
                    module_items.push(doc_item.into());
                }
                module_items.extend(self.parse_attributed_list(
                    Self::try_parse_module_item,
                    is_of_kind!(rbrace),
                    MODULE_ITEM_DESCRIPTION,
                ));
                let items = ModuleItemList::new_green(self.db, &module_items);
                let rbrace = self.parse_token::<TerminalRBrace<'_>>();
                ModuleBody::new_green(self.db, lbrace, items, rbrace).into()
            }
            SyntaxKind::TerminalSemicolon => self.take::<TerminalSemicolon<'_>>().into(),
            _ => self
                .create_and_report_missing::<TerminalSemicolon<'_>>(
                    ParserDiagnosticKind::ExpectedSemicolonOrBody,
                )
                .into(),
        };

        ItemModule::new_green(self.db, attributes, visibility, module_kw, name, body)
    }

    /// Assumes the current token is Struct.
    /// Expected pattern: `struct<Identifier>{<ParamList>}`
    fn expect_item_struct(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemStructGreen<'a> {
        let struct_kw = self.take::<TerminalStruct<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let lbrace = self.parse_token::<TerminalLBrace<'_>>();
        let members = self.parse_member_list();
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
        ItemStruct::new_green(
            self.db,
            attributes,
            visibility,
            struct_kw,
            name,
            generic_params,
            lbrace,
            members,
            rbrace,
        )
    }

    /// Assumes the current token is Enum.
    /// Expected pattern: `enum<Identifier>{<ParamList>}`
    fn expect_item_enum(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemEnumGreen<'a> {
        let enum_kw = self.take::<TerminalEnum<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let lbrace = self.parse_token::<TerminalLBrace<'_>>();
        let variants = self.parse_variant_list();
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
        ItemEnum::new_green(
            self.db,
            attributes,
            visibility,
            enum_kw,
            name,
            generic_params,
            lbrace,
            variants,
            rbrace,
        )
    }

    /// Assumes the current token is type.
    /// Expected pattern: `type <Identifier>{<ParamList>} = <TypeExpression>`
    fn expect_item_type_alias(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemTypeAliasGreen<'a> {
        let type_kw = self.take::<TerminalType<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let eq = self.parse_token::<TerminalEq<'_>>();
        let ty = self.parse_type_expr();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        ItemTypeAlias::new_green(
            self.db,
            attributes,
            visibility,
            type_kw,
            name,
            generic_params,
            eq,
            ty,
            semicolon,
        )
    }

    /// Expected pattern: `<ParenthesizedParamList><ReturnTypeClause>`
    fn expect_function_signature(&mut self) -> FunctionSignatureGreen<'a> {
        let lparen = self.parse_token::<TerminalLParen<'_>>();
        let params = self.parse_param_list();
        let rparen = self.parse_token::<TerminalRParen<'_>>();
        let return_type_clause = self.parse_option_return_type_clause();
        let implicits_clause = self.parse_option_implicits_clause();
        let optional_no_panic = if self.peek().kind == SyntaxKind::TerminalNoPanic {
            self.take::<TerminalNoPanic<'_>>().into()
        } else {
            OptionTerminalNoPanicEmpty::new_green(self.db).into()
        };

        FunctionSignature::new_green(
            self.db,
            lparen,
            params,
            rparen,
            return_type_clause,
            implicits_clause,
            optional_no_panic,
        )
    }

    /// Assumes the current token is [TerminalConst].
    /// Expected pattern: `const <Identifier> = <Expr>;`
    fn expect_item_const(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
        const_kw: TerminalConstGreen<'a>,
    ) -> ItemConstantGreen<'a> {
        let name = self.parse_identifier();
        let type_clause = self.parse_type_clause(ErrorRecovery {
            should_stop: is_of_kind!(eq, semicolon, module_item_kw),
        });
        let eq = self.parse_token::<TerminalEq<'_>>();
        let expr = self.parse_expr();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();

        ItemConstant::new_green(
            self.db,
            attributes,
            visibility,
            const_kw,
            name,
            type_clause,
            eq,
            expr,
            semicolon,
        )
    }

    /// Assumes the current token is Extern.
    /// Expected pattern: `extern(<FunctionDeclaration>|type<Identifier>);`
    fn expect_item_extern<T: From<ItemExternFunctionGreen<'a>> + From<ItemExternTypeGreen<'a>>>(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> T {
        match self.expect_item_extern_inner(attributes, visibility) {
            ExternItem::Function(x) => x.into(),
            ExternItem::Type(x) => x.into(),
        }
    }

    /// Assumes the current token is Extern.
    /// Expected pattern: `extern(<FunctionDeclaration>|type<Identifier>);`
    fn expect_item_extern_inner(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ExternItem<'a> {
        let extern_kw = self.take::<TerminalExtern<'_>>();
        match self.peek().kind {
            kind @ (SyntaxKind::TerminalFunction | SyntaxKind::TerminalConst) => {
                let (optional_const, function_kw) = if kind == SyntaxKind::TerminalConst {
                    (
                        self.take::<TerminalConst<'_>>().into(),
                        self.parse_token::<TerminalFunction<'_>>(),
                    )
                } else {
                    (
                        OptionTerminalConstEmpty::new_green(self.db).into(),
                        self.take::<TerminalFunction<'_>>(),
                    )
                };
                let declaration = self.expect_function_declaration_ex(optional_const, function_kw);
                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                ExternItem::Function(ItemExternFunction::new_green(
                    self.db,
                    attributes,
                    visibility,
                    extern_kw,
                    declaration,
                    semicolon,
                ))
            }
            _ => {
                // TODO(spapini): Don't return ItemExternType if we don't see a type.
                let type_kw = self.parse_token::<TerminalType<'_>>();

                let name = self.parse_identifier();
                let generic_params = self.parse_optional_generic_params();
                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                // If the next token is not type, assume it is missing.
                ExternItem::Type(ItemExternType::new_green(
                    self.db,
                    attributes,
                    visibility,
                    extern_kw,
                    type_kw,
                    name,
                    generic_params,
                    semicolon,
                ))
            }
        }
    }

    /// Assumes the current token is Use.
    /// Expected pattern: `use<Path>;`
    fn expect_item_use(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemUseGreen<'a> {
        let use_kw = self.take::<TerminalUse<'_>>();
        let dollar = match self.peek().kind {
            SyntaxKind::TerminalDollar => self.take::<TerminalDollar<'_>>().into(),
            _ => OptionTerminalDollarEmpty::new_green(self.db).into(),
        };
        let use_path = self.parse_use_path();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        ItemUse::new_green(self.db, attributes, visibility, use_kw, dollar, use_path, semicolon)
    }

    /// Assumes the current token is Macro.
    /// Expected pattern: `macro<Identifier>{<MacroRulesList>}`
    fn expect_item_macro_declaration(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemMacroDeclarationGreen<'a> {
        let macro_kw = self.take::<TerminalMacro<'_>>();
        let name = self.parse_identifier();
        let lbrace = self.parse_token::<TerminalLBrace<'_>>();
        let macro_rules = MacroRulesList::new_green(
            self.db,
            &self.parse_list(Self::try_parse_macro_rule, is_of_kind!(rbrace), "macro rule"),
        );
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
        ItemMacroDeclaration::new_green(
            self.db,
            attributes,
            visibility,
            macro_kw,
            name,
            lbrace,
            macro_rules,
            rbrace,
        )
    }

    /// Returns a GreenId of a node with a MacroRule kind or TryParseFailure if a macro rule can't
    /// be parsed.
    fn try_parse_macro_rule(&mut self) -> TryParseResult<MacroRuleGreen<'a>> {
        let previous_macro_parsing_context =
            mem::replace(&mut self.macro_parsing_context, MacroParsingContext::MacroRule);
        let wrapped_macro = match self.peek().kind {
            SyntaxKind::TerminalLParen => self
                .wrap_macro::<TerminalLParen<'_>, TerminalRParen<'_>, _, _>(
                    ParenthesizedMacro::new_green,
                )
                .into(),
            SyntaxKind::TerminalLBrace => self
                .wrap_macro::<TerminalLBrace<'_>, TerminalRBrace<'_>, _, _>(BracedMacro::new_green)
                .into(),
            SyntaxKind::TerminalLBrack => self
                .wrap_macro::<TerminalLBrack<'_>, TerminalRBrack<'_>, _, _>(
                    BracketedMacro::new_green,
                )
                .into(),
            _ => {
                self.macro_parsing_context = previous_macro_parsing_context;
                return Err(TryParseFailure::SkipToken);
            }
        };
        let arrow = self.parse_token::<TerminalMatchArrow<'_>>();
        if let Err(SkippedError(span)) = self.skip_until(is_of_kind!(rbrace, lbrace)) {
            self.add_diagnostic(
                ParserDiagnosticKind::SkippedElement { element_name: "'{'".into() },
                span,
            );
        }
        let macro_body = if self.peek().kind == SyntaxKind::TerminalLBrace {
            self.macro_parsing_context = MacroParsingContext::MacroExpansion;
            self.wrap_macro::<TerminalLBrace<'_>, TerminalRBrace<'_>, _, _>(BracedMacro::new_green)
        } else {
            BracedMacro::new_green(
                self.db,
                self.create_and_report_missing_terminal::<TerminalLBrace<'_>>(),
                MacroElements::new_green(self.db, &[]),
                self.create_and_report_missing_terminal::<TerminalRBrace<'_>>(),
            )
        };
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        self.macro_parsing_context = previous_macro_parsing_context;
        Ok(MacroRule::new_green(self.db, wrapped_macro, arrow, macro_body, semicolon))
    }
    /// Returns a GreenId of a node with a MacroRuleElement kind or TryParseFailure if a macro rule
    /// element can't be parsed.
    /// Expected pattern: Either any token or a matcher of the pattern $ident:kind.
    fn try_parse_macro_element(&mut self) -> TryParseResult<MacroElementGreen<'a>> {
        match self.peek().kind {
            SyntaxKind::TerminalDollar => {
                let dollar: TerminalDollarGreen<'_> = self.take::<TerminalDollar<'_>>();
                match self.peek().kind {
                    SyntaxKind::TerminalLParen => {
                        let lparen = self.take::<TerminalLParen<'_>>();
                        let elements = self.expect_wrapped_macro();
                        let rparen = self.parse_token::<TerminalRParen<'_>>();
                        let separator: OptionTerminalCommaGreen<'_> = match self.peek().kind {
                            SyntaxKind::TerminalComma => self.take::<TerminalComma<'_>>().into(),
                            _ => OptionTerminalCommaEmpty::new_green(self.db).into(),
                        };
                        let operator = match self.peek().kind {
                            SyntaxKind::TerminalQuestionMark => {
                                self.take::<TerminalQuestionMark<'_>>().into()
                            }
                            SyntaxKind::TerminalPlus => self.take::<TerminalPlus<'_>>().into(),
                            SyntaxKind::TerminalMul => self.take::<TerminalMul<'_>>().into(),
                            _ => MacroRepetitionOperator::missing(self.db),
                        };
                        Ok(MacroRepetition::new_green(
                            self.db, dollar, lparen, elements, rparen, separator, operator,
                        )
                        .into())
                    }
                    _ => {
                        let ident = self.parse_identifier();
                        let param_kind: OptionParamKindGreen<'_> = if self.peek().kind
                            == SyntaxKind::TerminalColon
                        {
                            let colon = self.parse_token::<TerminalColon<'_>>();
                            let kind = self.parse_macro_rule_param_kind();
                            let result = ParamKind::new_green(self.db, colon, kind).into();
                            if let MacroParsingContext::MacroExpansion = self.macro_parsing_context
                            {
                                self.add_diagnostic(
                                    ParserDiagnosticKind::InvalidParamKindInMacroExpansion,
                                    TextSpan::new_with_width(self.offset, self.current_width),
                                );
                            }
                            result
                        } else {
                            if let MacroParsingContext::MacroRule = self.macro_parsing_context {
                                self.add_diagnostic(
                                    ParserDiagnosticKind::InvalidParamKindInMacroRule,
                                    TextSpan::new_with_width(self.offset, self.current_width),
                                );
                            }
                            OptionParamKindEmpty::new_green(self.db).into()
                        };
                        self.macro_parsing_context = MacroParsingContext::None;
                        Ok(MacroParam::new_green(self.db, dollar, ident, param_kind).into())
                    }
                }
            }
            SyntaxKind::TerminalLParen
            | SyntaxKind::TerminalLBrace
            | SyntaxKind::TerminalLBrack => {
                let subtree = self.parse_macro_elements();
                Ok(MacroWrapper::new_green(self.db, subtree).into())
            }
            _ => {
                let token = self.parse_token_tree_leaf();
                Ok(token.into())
            }
        }
    }

    fn parse_macro_elements(&mut self) -> WrappedMacroGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalLParen => self
                .wrap_macro::<TerminalLParen<'_>, TerminalRParen<'_>, _, _>(
                    ParenthesizedMacro::new_green,
                )
                .into(),
            SyntaxKind::TerminalLBrace => self
                .wrap_macro::<TerminalLBrace<'_>, TerminalRBrace<'_>, _, _>(BracedMacro::new_green)
                .into(),
            SyntaxKind::TerminalLBrack => self
                .wrap_macro::<TerminalLBrack<'_>, TerminalRBrack<'_>, _, _>(
                    BracketedMacro::new_green,
                )
                .into(),
            _ => unreachable!("parse_macro_elements called on non-delimiter token"),
        }
    }

    fn expect_wrapped_macro(&mut self) -> MacroElementsGreen<'a> {
        let mut elements: Vec<MacroElementGreen<'a>> = vec![];
        while !matches!(
            self.peek().kind,
            SyntaxKind::TerminalRParen
                | SyntaxKind::TerminalRBrace
                | SyntaxKind::TerminalRBrack
                | SyntaxKind::TerminalEndOfFile
        ) {
            let element = self.try_parse_macro_element();
            match element {
                Ok(element) => elements.push(element),
                Err(TryParseFailure::SkipToken) => {
                    let _ = self.skip_until(is_of_kind!(rparen, rbrace, rbrack));
                    break;
                }
                Err(TryParseFailure::DoNothing) => break,
            }
        }
        MacroElements::new_green(self.db, &elements)
    }

    fn wrap_macro<
        LTerminal: syntax::node::Terminal<'a>,
        RTerminal: syntax::node::Terminal<'a>,
        ListGreen,
        NewGreen: Fn(
            &'a dyn Database,
            LTerminal::Green,
            MacroElementsGreen<'a>,
            RTerminal::Green,
        ) -> ListGreen,
    >(
        &mut self,
        new_green: NewGreen,
    ) -> ListGreen {
        let l_term = self.take::<LTerminal>();
        let elements = self.expect_wrapped_macro();
        let r_term = self.parse_token::<RTerminal>();
        new_green(self.db, l_term, elements, r_term)
    }

    /// Returns a GreenId of a node with a MacroRuleParamKind kind.
    fn parse_macro_rule_param_kind(&mut self) -> MacroParamKindGreen<'a> {
        let peeked = self.peek();
        match (peeked.kind, peeked.text.long(self.db).as_str()) {
            (SyntaxKind::TerminalIdentifier, "ident") => {
                ParamIdent::new_green(self.db, self.parse_token::<TerminalIdentifier<'_>>()).into()
            }
            (SyntaxKind::TerminalIdentifier, "expr") => {
                ParamExpr::new_green(self.db, self.parse_token::<TerminalIdentifier<'_>>()).into()
            }
            _ => self.create_and_report_missing::<MacroParamKind<'_>>(
                ParserDiagnosticKind::MissingMacroRuleParamKind,
            ),
        }
    }

    /// Returns a GreenId of a node with a UsePath kind or TryParseFailure if can't parse a UsePath.
    fn try_parse_use_path(&mut self) -> TryParseResult<UsePathGreen<'a>> {
        if !matches!(
            self.peek().kind,
            SyntaxKind::TerminalLBrace | SyntaxKind::TerminalIdentifier | SyntaxKind::TerminalMul
        ) {
            return Err(TryParseFailure::SkipToken);
        }
        Ok(self.parse_use_path())
    }

    /// Returns a GreenId of a node with a UsePath kind.
    fn parse_use_path(&mut self) -> UsePathGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalLBrace => {
                let lbrace = self.parse_token::<TerminalLBrace<'_>>();
                let items = UsePathList::new_green(self.db,
                    &self.parse_separated_list::<
                        UsePath<'_>, TerminalComma<'_>, UsePathListElementOrSeparatorGreen<'_>
                    >(
                        Self::try_parse_use_path,
                        is_of_kind!(rbrace, module_item_kw),
                        "path segment",
                    ));
                let rbrace = self.parse_token::<TerminalRBrace<'_>>();
                UsePathMulti::new_green(self.db, lbrace, items, rbrace).into()
            }
            SyntaxKind::TerminalMul => {
                let star = self.parse_token::<TerminalMul<'_>>();
                UsePathStar::new_green(self.db, star).into()
            }
            _ => {
                if let Ok(ident) = self.try_parse_identifier() {
                    let ident = PathSegmentSimple::new_green(self.db, ident).into();
                    match self.peek().kind {
                        SyntaxKind::TerminalColonColon => {
                            let colon_colon = self.parse_token::<TerminalColonColon<'_>>();
                            let use_path = self.parse_use_path();
                            UsePathSingle::new_green(self.db, ident, colon_colon, use_path).into()
                        }
                        SyntaxKind::TerminalAs => {
                            let as_kw = self.take::<TerminalAs<'_>>();
                            let alias = self.parse_identifier();
                            let alias_clause = AliasClause::new_green(self.db, as_kw, alias).into();
                            UsePathLeaf::new_green(self.db, ident, alias_clause).into()
                        }
                        _ => {
                            let alias_clause = OptionAliasClauseEmpty::new_green(self.db).into();
                            UsePathLeaf::new_green(self.db, ident, alias_clause).into()
                        }
                    }
                } else {
                    let missing = self.create_and_report_missing::<TerminalIdentifier<'_>>(
                        ParserDiagnosticKind::MissingPathSegment,
                    );
                    let ident = PathSegmentSimple::new_green(self.db, missing).into();
                    UsePathLeaf::new_green(
                        self.db,
                        ident,
                        OptionAliasClauseEmpty::new_green(self.db).into(),
                    )
                    .into()
                }
            }
        }
    }

    /// Returns a GreenId of a node with an identifier kind or TryParseFailure if an identifier
    /// can't be parsed.
    /// Note that if the terminal is a keyword or an underscore, it is skipped, and
    /// Some(missing-identifier) is returned.
    fn try_parse_identifier(&mut self) -> TryParseResult<TerminalIdentifierGreen<'a>> {
        let peeked = self.peek();
        if peeked.kind.is_keyword_terminal() {
            // TODO(spapini): don't skip every keyword. Instead, pass a recovery set.
            Ok(self.skip_token_and_return_missing::<TerminalIdentifier<'_>>(
                ParserDiagnosticKind::ReservedIdentifier {
                    identifier: peeked.text.long(self.db).to_string(),
                },
            ))
        } else if peeked.kind == SyntaxKind::TerminalUnderscore {
            Ok(self.skip_token_and_return_missing::<TerminalIdentifier<'_>>(
                ParserDiagnosticKind::UnderscoreNotAllowedAsIdentifier,
            ))
        } else {
            self.try_parse_token::<TerminalIdentifier<'_>>()
        }
    }
    /// Returns whether the current token is an identifier, a keyword or an underscore ('_'),
    /// without consuming it. This should be used mostly, instead of checking whether the current
    /// token is an identifier, because in many cases we'd want to consume the keyword/underscore as
    /// the identifier and raise a relevant diagnostic
    /// (ReservedIdentifier/UnderscoreNotAllowedAsIdentifier).
    fn is_peek_identifier_like(&self) -> bool {
        let kind = self.peek().kind;
        kind.is_keyword_terminal()
            || matches!(
                kind,
                SyntaxKind::TerminalUnderscore
                    | SyntaxKind::TerminalIdentifier
                    | SyntaxKind::TerminalDollar
            )
    }

    /// Returns a GreenId of a node with an identifier kind.
    fn parse_identifier(&mut self) -> TerminalIdentifierGreen<'a> {
        match self.try_parse_identifier() {
            Ok(identifier) => identifier,
            Err(_) => self.create_and_report_missing_terminal::<TerminalIdentifier<'_>>(),
        }
    }

    /// Returns a GreenId of node visibility.
    fn parse_visibility(&mut self) -> VisibilityGreen<'a> {
        match self.try_parse_visibility_pub() {
            Some(visibility) => visibility.into(),
            None => VisibilityDefault::new_green(self.db).into(),
        }
    }

    /// Returns a GreenId of node with pub visibility or None if not starting with "pub".
    fn try_parse_visibility_pub(&mut self) -> Option<VisibilityPubGreen<'a>> {
        require(self.peek().kind == SyntaxKind::TerminalPub)?;
        let pub_kw = self.take::<TerminalPub<'_>>();
        let argument_clause = if self.peek().kind != SyntaxKind::TerminalLParen {
            OptionVisibilityPubArgumentClauseEmpty::new_green(self.db).into()
        } else {
            let lparen = self.parse_token::<TerminalLParen<'_>>();
            let argument = self.parse_token::<TerminalIdentifier<'_>>();
            let rparen = self.parse_token::<TerminalRParen<'_>>();
            VisibilityPubArgumentClause::new_green(self.db, lparen, argument, rparen).into()
        };
        Some(VisibilityPub::new_green(self.db, pub_kw, argument_clause))
    }

    /// Returns a GreenId of a node with an attribute list kind or TryParseFailure if an attribute
    /// list can't be parsed.
    /// `expected_elements_str` are the expected elements that these attributes are parsed for.
    /// Note: it should not include "attribute".
    fn try_parse_attribute_list(
        &mut self,
        expected_elements_str: &str,
    ) -> TryParseResult<AttributeListGreen<'a>> {
        if self.peek().kind == SyntaxKind::TerminalHash {
            Ok(self.parse_attribute_list(expected_elements_str))
        } else {
            Err(TryParseFailure::SkipToken)
        }
    }

    /// Parses an attribute list.
    /// `expected_elements_str` are the expected elements that these attributes are parsed for.
    /// Note: it should not include "attribute".
    fn parse_attribute_list(&mut self, expected_elements_str: &str) -> AttributeListGreen<'a> {
        AttributeList::new_green(
            self.db,
            &self.parse_list(
                Self::try_parse_attribute,
                |x| x != SyntaxKind::TerminalHash,
                &or_an_attribute!(expected_elements_str),
            ),
        )
    }

    /// Returns a GreenId of a node with an attribute kind or TryParseFailure if an attribute can't
    /// be parsed.
    fn try_parse_attribute(&mut self) -> TryParseResult<AttributeGreen<'a>> {
        match self.peek().kind {
            SyntaxKind::TerminalHash => {
                let hash = self.take::<TerminalHash<'_>>();
                let lbrack = self.parse_token::<TerminalLBrack<'_>>();
                let attr = self.parse_path();
                let arguments = self.try_parse_parenthesized_argument_list();
                let rbrack = self.parse_token::<TerminalRBrack<'_>>();

                Ok(Attribute::new_green(self.db, hash, lbrack, attr, arguments, rbrack))
            }
            _ => Err(TryParseFailure::SkipToken),
        }
    }

    /// Assumes the current token is Function.
    /// Expected pattern: `<FunctionDeclaration>`
    fn expect_function_declaration(
        &mut self,
        optional_const: OptionTerminalConstGreen<'a>,
    ) -> FunctionDeclarationGreen<'a> {
        let function_kw = self.take::<TerminalFunction<'_>>();
        self.expect_function_declaration_ex(optional_const, function_kw)
    }

    /// Assumes the current token is Function.
    /// Expected pattern: `<FunctionDeclaration>`
    fn expect_function_declaration_ex(
        &mut self,
        optional_const: OptionTerminalConstGreen<'a>,
        function_kw: TerminalFunctionGreen<'a>,
    ) -> FunctionDeclarationGreen<'a> {
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let signature = self.expect_function_signature();

        FunctionDeclaration::new_green(
            self.db,
            optional_const,
            function_kw,
            name,
            generic_params,
            signature,
        )
    }

    /// Assumes the current token is Function.
    /// Expected pattern: `<FunctionDeclaration><Block>`
    fn expect_item_function_with_body(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
        optional_const: OptionTerminalConstGreen<'a>,
    ) -> FunctionWithBodyGreen<'a> {
        let declaration = self.expect_function_declaration(optional_const);
        let function_body = self.parse_block();
        FunctionWithBody::new_green(self.db, attributes, visibility, declaration, function_body)
    }

    /// Assumes the current token is Trait.
    fn expect_item_trait(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemTraitGreen<'a> {
        let trait_kw = self.take::<TerminalTrait<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let body = if self.peek().kind == SyntaxKind::TerminalLBrace {
            let lbrace = self.take::<TerminalLBrace<'_>>();
            let items = TraitItemList::new_green(
                self.db,
                &self.parse_attributed_list(
                    Self::try_parse_trait_item,
                    is_of_kind!(rbrace, module_item_kw),
                    TRAIT_ITEM_DESCRIPTION,
                ),
            );
            let rbrace = self.parse_token::<TerminalRBrace<'_>>();
            TraitBody::new_green(self.db, lbrace, items, rbrace).into()
        } else {
            self.parse_token::<TerminalSemicolon<'_>>().into()
        };

        ItemTrait::new_green(self.db, attributes, visibility, trait_kw, name, generic_params, body)
    }

    /// Returns a GreenId of a node with a TraitItem.* kind (see
    /// [syntax::node::ast::TraitItem]), or TryParseFailure if a trait item can't be parsed.
    pub fn try_parse_trait_item(&mut self) -> TryParseResult<TraitItemGreen<'a>> {
        let maybe_attributes = self.try_parse_attribute_list(TRAIT_ITEM_DESCRIPTION);

        let (has_attrs, attributes) = match maybe_attributes {
            Ok(attributes) => (true, attributes),
            Err(_) => (false, AttributeList::new_green(self.db, &[])),
        };

        match self.peek().kind {
            SyntaxKind::TerminalFunction => Ok(self
                .expect_trait_item_function(
                    attributes,
                    OptionTerminalConstEmpty::new_green(self.db).into(),
                )
                .into()),
            SyntaxKind::TerminalType => Ok(self.expect_trait_item_type(attributes).into()),
            SyntaxKind::TerminalConst => {
                let const_kw = self.take::<TerminalConst<'_>>();
                Ok(if self.peek().kind == SyntaxKind::TerminalFunction {
                    self.expect_trait_item_function(attributes, const_kw.into()).into()
                } else {
                    self.expect_trait_item_const(attributes, const_kw).into()
                })
            }
            SyntaxKind::TerminalImpl => Ok(self.expect_trait_item_impl(attributes).into()),
            _ => {
                if has_attrs {
                    Ok(self.skip_taken_node_and_return_missing::<TraitItem<'_>>(
                        attributes,
                        ParserDiagnosticKind::AttributesWithoutTraitItem,
                    ))
                } else {
                    Err(TryParseFailure::SkipToken)
                }
            }
        }
    }

    /// Assumes the current token is Function.
    /// Expected pattern: `<FunctionDeclaration><SemiColon>`
    fn expect_trait_item_function(
        &mut self,
        attributes: AttributeListGreen<'a>,
        optional_const: OptionTerminalConstGreen<'a>,
    ) -> TraitItemFunctionGreen<'a> {
        let declaration = self.expect_function_declaration(optional_const);
        let body = if self.peek().kind == SyntaxKind::TerminalLBrace {
            self.parse_block().into()
        } else {
            self.parse_token::<TerminalSemicolon<'_>>().into()
        };
        TraitItemFunction::new_green(self.db, attributes, declaration, body)
    }

    /// Assumes the current token is Type.
    /// Expected pattern: `type <name>;`
    fn expect_trait_item_type(
        &mut self,
        attributes: AttributeListGreen<'a>,
    ) -> TraitItemTypeGreen<'a> {
        let type_kw = self.take::<TerminalType<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        TraitItemType::new_green(self.db, attributes, type_kw, name, generic_params, semicolon)
    }

    /// Assumes the current token is Const.
    /// Expected pattern: `const <name>: <type>;`
    fn expect_trait_item_const(
        &mut self,
        attributes: AttributeListGreen<'a>,
        const_kw: TerminalConstGreen<'a>,
    ) -> TraitItemConstantGreen<'a> {
        let name = self.parse_identifier();
        let type_clause = self.parse_type_clause(ErrorRecovery {
            should_stop: is_of_kind!(eq, semicolon, module_item_kw),
        });
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();

        TraitItemConstant::new_green(self.db, attributes, const_kw, name, type_clause, semicolon)
    }

    /// Assumes the current token is Impl.
    /// Expected pattern: `impl <name>: <trait_path>;`
    fn expect_trait_item_impl(
        &mut self,
        attributes: AttributeListGreen<'a>,
    ) -> TraitItemImplGreen<'a> {
        let impl_kw = self.take::<TerminalImpl<'_>>();
        let name = self.parse_identifier();
        let colon = self.parse_token::<TerminalColon<'_>>();
        let trait_path = self.parse_type_path();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        TraitItemImpl::new_green(self.db, attributes, impl_kw, name, colon, trait_path, semicolon)
    }

    /// Assumes the current token is Impl.
    fn expect_module_item_impl(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ModuleItemGreen<'a> {
        match self.expect_item_impl_inner(attributes, visibility, false) {
            ImplItemOrAlias::Item(green) => green.into(),
            ImplItemOrAlias::Alias(green) => green.into(),
        }
    }

    /// Assumes the current token is Impl.
    /// Expects an impl impl-item (impl alias syntax): `impl <name> = <path>;`.
    fn expect_impl_item_impl(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
    ) -> ItemImplAliasGreen<'a> {
        extract_matches!(
            self.expect_item_impl_inner(attributes, visibility, true),
            ImplItemOrAlias::Alias
        )
    }

    /// Assumes the current token is Impl.
    /// Expects either an impl item (`impl <name> of <trait_path> {<impl_body>}`) or and impl alias
    /// `impl <name> = <path>;`.
    /// If `only_allow_alias` is true, always returns an ImplItemOrAlias::Alias.
    fn expect_item_impl_inner(
        &mut self,
        attributes: AttributeListGreen<'a>,
        visibility: VisibilityGreen<'a>,
        only_allow_alias: bool,
    ) -> ImplItemOrAlias<'a> {
        let impl_kw = self.take::<TerminalImpl<'_>>();
        let name = self.parse_identifier();
        let generic_params = self.parse_optional_generic_params();

        if self.peek().kind == SyntaxKind::TerminalEq || only_allow_alias {
            let eq = self.parse_token::<TerminalEq<'_>>();
            let impl_path = self.parse_type_path();
            let semicolon = self.parse_token::<TerminalSemicolon<'_>>();

            return ImplItemOrAlias::Alias(ItemImplAlias::new_green(
                self.db,
                attributes,
                visibility,
                impl_kw,
                name,
                generic_params,
                eq,
                impl_path,
                semicolon,
            ));
        }

        let of_kw = self.parse_token::<TerminalOf<'_>>();
        let trait_path = self.parse_type_path();
        let body = if self.peek().kind == SyntaxKind::TerminalLBrace {
            let lbrace = self.take::<TerminalLBrace<'_>>();
            let items = ImplItemList::new_green(
                self.db,
                &self.parse_attributed_list(
                    Self::try_parse_impl_item,
                    is_of_kind!(rbrace),
                    IMPL_ITEM_DESCRIPTION,
                ),
            );
            let rbrace = self.parse_token::<TerminalRBrace<'_>>();
            ImplBody::new_green(self.db, lbrace, items, rbrace).into()
        } else {
            self.parse_token::<TerminalSemicolon<'_>>().into()
        };

        ImplItemOrAlias::Item(ItemImpl::new_green(
            self.db,
            attributes,
            visibility,
            impl_kw,
            name,
            generic_params,
            of_kw,
            trait_path,
            body,
        ))
    }

    /// Returns a GreenId of a node with a ImplItem.* kind (see
    /// [syntax::node::ast::ImplItem]), or TryParseFailure if an impl item can't be parsed.
    pub fn try_parse_impl_item(&mut self) -> TryParseResult<ImplItemGreen<'a>> {
        let maybe_attributes = self.try_parse_attribute_list(IMPL_ITEM_DESCRIPTION);

        let (has_attrs, attributes) = match maybe_attributes {
            Ok(attributes) => (true, attributes),
            Err(_) => (false, AttributeList::new_green(self.db, &[])),
        };

        // No visibility in impls, as these just implements the options of a trait, which is always
        // pub.
        let visibility = VisibilityDefault::new_green(self.db).into();

        match self.peek().kind {
            SyntaxKind::TerminalFunction => Ok(self
                .expect_item_function_with_body(
                    attributes,
                    visibility,
                    OptionTerminalConstEmpty::new_green(self.db).into(),
                )
                .into()),
            SyntaxKind::TerminalType => {
                Ok(self.expect_item_type_alias(attributes, visibility).into())
            }
            SyntaxKind::TerminalConst => {
                let const_kw = self.take::<TerminalConst<'_>>();
                Ok(if self.peek().kind == SyntaxKind::TerminalFunction {
                    self.expect_item_function_with_body(attributes, visibility, const_kw.into())
                        .into()
                } else {
                    self.expect_item_const(attributes, visibility, const_kw).into()
                })
            }
            SyntaxKind::TerminalImpl => {
                Ok(self.expect_impl_item_impl(attributes, visibility).into())
            }
            // These are not supported semantically.
            SyntaxKind::TerminalModule => {
                Ok(self.expect_item_module(attributes, visibility).into())
            }
            SyntaxKind::TerminalStruct => {
                Ok(self.expect_item_struct(attributes, visibility).into())
            }
            SyntaxKind::TerminalEnum => Ok(self.expect_item_enum(attributes, visibility).into()),
            SyntaxKind::TerminalExtern => Ok(self.expect_item_extern(attributes, visibility)),
            SyntaxKind::TerminalUse => Ok(self.expect_item_use(attributes, visibility).into()),
            SyntaxKind::TerminalTrait => Ok(self.expect_item_trait(attributes, visibility).into()),
            _ => {
                if has_attrs {
                    Ok(self.skip_taken_node_and_return_missing::<ImplItem<'_>>(
                        attributes,
                        ParserDiagnosticKind::AttributesWithoutImplItem,
                    ))
                } else {
                    Err(TryParseFailure::SkipToken)
                }
            }
        }
    }

    /// Assumes the current token is TerminalNot.
    fn expect_item_inline_macro(
        &mut self,
        attributes: AttributeListGreen<'a>,
        path: ExprPathGreen<'a>,
    ) -> ItemInlineMacroGreen<'a> {
        let bang = self.parse_token::<TerminalNot<'_>>();
        self.parse_item_inline_macro_given_bang(attributes, path, bang)
    }

    /// Returns a GreenId of a node with an ItemInlineMacro kind, given the bang ('!') token.
    fn parse_item_inline_macro_given_bang(
        &mut self,
        attributes: AttributeListGreen<'a>,
        path: ExprPathGreen<'a>,
        bang: TerminalNotGreen<'a>,
    ) -> ItemInlineMacroGreen<'a> {
        let token_tree_node = self.parse_token_tree_node();
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        ItemInlineMacro::new_green(self.db, attributes, path, bang, token_tree_node, semicolon)
    }

    // ------------------------------- Expressions -------------------------------

    /// Returns a GreenId of a node with an Expr.* kind (see [syntax::node::ast::Expr])
    /// or TryParseFailure if an expression can't be parsed.
    pub fn try_parse_expr(&mut self) -> TryParseResult<ExprGreen<'a>> {
        self.try_parse_expr_limited(MAX_PRECEDENCE, LbraceAllowed::Allow, AndLetBehavior::Simple)
    }
    /// Returns a GreenId of a node with an Expr.* kind (see [syntax::node::ast::Expr])
    /// or a node with kind ExprMissing if an expression can't be parsed.
    pub fn parse_expr(&mut self) -> ExprGreen<'a> {
        match self.try_parse_expr() {
            Ok(green) => green,
            Err(_) => {
                self.create_and_report_missing::<Expr<'_>>(ParserDiagnosticKind::MissingExpression)
            }
        }
    }

    /// Assumes the current token is a binary operator. Otherwise it might panic.
    ///
    /// Returns a GreenId of the operator.
    fn parse_binary_operator(&mut self) -> BinaryOperatorGreen<'a> {
        // Note that if this code is not reached you might need to add the operator to
        // `get_post_operator_precedence`.
        match self.peek().kind {
            SyntaxKind::TerminalDot => self.take::<TerminalDot<'_>>().into(),
            SyntaxKind::TerminalMul => self.take::<TerminalMul<'_>>().into(),
            SyntaxKind::TerminalMulEq => self.take::<TerminalMulEq<'_>>().into(),
            SyntaxKind::TerminalDiv => self.take::<TerminalDiv<'_>>().into(),
            SyntaxKind::TerminalDivEq => self.take::<TerminalDivEq<'_>>().into(),
            SyntaxKind::TerminalMod => self.take::<TerminalMod<'_>>().into(),
            SyntaxKind::TerminalModEq => self.take::<TerminalModEq<'_>>().into(),
            SyntaxKind::TerminalPlus => self.take::<TerminalPlus<'_>>().into(),
            SyntaxKind::TerminalPlusEq => self.take::<TerminalPlusEq<'_>>().into(),
            SyntaxKind::TerminalMinus => self.take::<TerminalMinus<'_>>().into(),
            SyntaxKind::TerminalMinusEq => self.take::<TerminalMinusEq<'_>>().into(),
            SyntaxKind::TerminalEq => self.take::<TerminalEq<'_>>().into(),
            SyntaxKind::TerminalEqEq => self.take::<TerminalEqEq<'_>>().into(),
            SyntaxKind::TerminalNeq => self.take::<TerminalNeq<'_>>().into(),
            SyntaxKind::TerminalLT => self.take::<TerminalLT<'_>>().into(),
            SyntaxKind::TerminalGT => self.take::<TerminalGT<'_>>().into(),
            SyntaxKind::TerminalLE => self.take::<TerminalLE<'_>>().into(),
            SyntaxKind::TerminalGE => self.take::<TerminalGE<'_>>().into(),
            SyntaxKind::TerminalAnd => self.take::<TerminalAnd<'_>>().into(),
            SyntaxKind::TerminalAndAnd => self.take::<TerminalAndAnd<'_>>().into(),
            SyntaxKind::TerminalOrOr => self.take::<TerminalOrOr<'_>>().into(),
            SyntaxKind::TerminalOr => self.take::<TerminalOr<'_>>().into(),
            SyntaxKind::TerminalXor => self.take::<TerminalXor<'_>>().into(),
            SyntaxKind::TerminalDotDot => self.take::<TerminalDotDot<'_>>().into(),
            SyntaxKind::TerminalDotDotEq => self.take::<TerminalDotDotEq<'_>>().into(),
            _ => unreachable!(),
        }
    }

    /// Assumes the current token is a unary operator, and returns a GreenId of the operator.
    fn expect_unary_operator(&mut self) -> UnaryOperatorGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalAt => self.take::<TerminalAt<'_>>().into(),
            SyntaxKind::TerminalAnd | SyntaxKind::TerminalAndAnd => {
                self.unglue_andand_for_unary();
                self.take::<TerminalAnd<'_>>().into()
            }
            SyntaxKind::TerminalNot => self.take::<TerminalNot<'_>>().into(),
            SyntaxKind::TerminalBitNot => self.take::<TerminalBitNot<'_>>().into(),
            SyntaxKind::TerminalMinus => self.take::<TerminalMinus<'_>>().into(),
            SyntaxKind::TerminalMul => self.take::<TerminalMul<'_>>().into(),
            _ => unreachable!(),
        }
    }

    /// Checks if the current token is a relational or equality operator (`<`, `>`, `<=`, `>=`,
    /// `==`, or `!=`).
    ///
    /// This function is used to determine if the given `SyntaxKind` represents a relational or
    /// equality operator, which is commonly used in binary expressions.
    ///
    /// # Parameters:
    /// - `kind`: The `SyntaxKind` of the current token.
    ///
    /// # Returns:
    /// `true` if the token is a relational or equality operator, otherwise `false`.
    fn is_comparison_operator(&self, kind: SyntaxKind) -> bool {
        matches!(
            kind,
            SyntaxKind::TerminalLT
                | SyntaxKind::TerminalGT
                | SyntaxKind::TerminalLE
                | SyntaxKind::TerminalGE
                | SyntaxKind::TerminalEqEq
                | SyntaxKind::TerminalNeq
        )
    }

    /// Returns a GreenId of a node with an Expr.* kind (see [syntax::node::ast::Expr])
    /// or TryParseFailure if such an expression can't be parsed.
    ///
    /// Parsing will be limited by:
    /// `parent_precedence` - parsing of binary operators limited to this.
    /// `lbrace_allowed` - See [LbraceAllowed].
    fn try_parse_expr_limited(
        &mut self,
        parent_precedence: usize,
        lbrace_allowed: LbraceAllowed,
        and_let_behavior: AndLetBehavior,
    ) -> TryParseResult<ExprGreen<'a>> {
        let mut expr = self.try_parse_atom_or_unary(lbrace_allowed)?;
        let mut child_op: Option<SyntaxKind> = None;
        loop {
            let peeked_kind = self.peek().kind;
            let Some(precedence) = get_post_operator_precedence(peeked_kind) else {
                return Ok(expr);
            };
            if precedence >= parent_precedence {
                return Ok(expr);
            }
            expr = match peeked_kind {
                // If the next two tokens are `&& let` (part of a let-chain), then they should be
                // parsed by the caller. Return immediately.
                SyntaxKind::TerminalAndAnd
                    if and_let_behavior == AndLetBehavior::Stop
                        && self.peek_next_next_kind() == SyntaxKind::TerminalLet =>
                {
                    return Ok(expr);
                }
                SyntaxKind::TerminalQuestionMark => ExprErrorPropagate::new_green(
                    self.db,
                    expr,
                    self.take::<TerminalQuestionMark<'_>>(),
                )
                .into(),
                SyntaxKind::TerminalLBrack => {
                    let lbrack = self.take::<TerminalLBrack<'_>>();
                    let index_expr = self.parse_expr();
                    let rbrack = self.parse_token::<TerminalRBrack<'_>>();
                    ExprIndexed::new_green(self.db, expr, lbrack, index_expr, rbrack).into()
                }
                current_op => {
                    if let Some(child_op_kind) = child_op
                        && self.is_comparison_operator(child_op_kind)
                        && self.is_comparison_operator(current_op)
                    {
                        self.add_diagnostic(
                            ParserDiagnosticKind::ConsecutiveMathOperators {
                                first_op: child_op_kind,
                                second_op: current_op,
                            },
                            TextSpan::cursor(self.offset.add_width(self.current_width)),
                        );
                    }
                    child_op = Some(current_op);
                    let op = self.parse_binary_operator();
                    let rhs = self.parse_expr_limited(precedence, lbrace_allowed, and_let_behavior);
                    ExprBinary::new_green(self.db, expr, op, rhs).into()
                }
            };
        }
    }

    /// Returns a GreenId of a node with ExprPath, ExprFunctionCall, ExprStructCtorCall,
    /// ExprParenthesized, ExprTuple or ExprUnary kind, or TryParseFailure if such an expression
    /// can't be parsed.
    ///
    /// `lbrace_allowed` - See [LbraceAllowed].
    fn try_parse_atom_or_unary(
        &mut self,
        lbrace_allowed: LbraceAllowed,
    ) -> TryParseResult<ExprGreen<'a>> {
        let Some(precedence) = get_unary_operator_precedence(self.peek().kind) else {
            return self.try_parse_atom(lbrace_allowed);
        };
        let op = self.expect_unary_operator();
        let expr = self.parse_expr_limited(precedence, lbrace_allowed, AndLetBehavior::Simple);
        Ok(ExprUnary::new_green(self.db, op, expr).into())
    }

    /// Returns a GreenId of a node with an Expr.* kind (see [syntax::node::ast::Expr]),
    /// excluding ExprBlock, or ExprMissing if such an expression can't be parsed.
    ///
    /// `lbrace_allowed` - See [LbraceAllowed].
    fn parse_expr_limited(
        &mut self,
        parent_precedence: usize,
        lbrace_allowed: LbraceAllowed,
        and_let_behavior: AndLetBehavior,
    ) -> ExprGreen<'a> {
        match self.try_parse_expr_limited(parent_precedence, lbrace_allowed, and_let_behavior) {
            Ok(green) => green,
            Err(_) => {
                self.create_and_report_missing::<Expr<'_>>(ParserDiagnosticKind::MissingExpression)
            }
        }
    }

    /// Returns a GreenId of a node with an
    /// ExprPath|ExprFunctionCall|ExprStructCtorCall|ExprParenthesized|ExprTuple kind, or
    /// TryParseFailure if such an expression can't be parsed.
    ///
    /// `lbrace_allowed` - See [LbraceAllowed].
    fn try_parse_atom(&mut self, lbrace_allowed: LbraceAllowed) -> TryParseResult<ExprGreen<'a>> {
        // TODO(yuval): support paths starting with "::".
        match self.peek().kind {
            SyntaxKind::TerminalIdentifier | SyntaxKind::TerminalDollar => {
                // Call parse_path() and not expect_path(), because it's cheap.
                let path = self.parse_path();
                match self.peek().kind {
                    SyntaxKind::TerminalLParen => Ok(self.expect_function_call(path).into()),
                    SyntaxKind::TerminalLBrace if lbrace_allowed == LbraceAllowed::Allow => {
                        Ok(self.expect_constructor_call(path).into())
                    }
                    SyntaxKind::TerminalNot => Ok(self.expect_macro_call(path).into()),
                    _ => Ok(path.into()),
                }
            }
            SyntaxKind::TerminalFalse => Ok(self.take::<TerminalFalse<'_>>().into()),
            SyntaxKind::TerminalTrue => Ok(self.take::<TerminalTrue<'_>>().into()),
            SyntaxKind::TerminalLiteralNumber => Ok(self.take_terminal_literal_number().into()),
            SyntaxKind::TerminalShortString => Ok(self.take_terminal_short_string().into()),
            SyntaxKind::TerminalString => Ok(self.take_terminal_string().into()),
            SyntaxKind::TerminalLParen => {
                // Note that LBrace is allowed inside parenthesis, even if `lbrace_allowed` is
                // [LbraceAllowed::Forbid].
                Ok(self.expect_parenthesized_expr())
            }
            SyntaxKind::TerminalLBrack => Ok(self.expect_fixed_size_array_expr().into()),
            SyntaxKind::TerminalLBrace if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.parse_block().into())
            }
            SyntaxKind::TerminalMatch if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.expect_match_expr().into())
            }
            SyntaxKind::TerminalIf if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.expect_if_expr().into())
            }
            SyntaxKind::TerminalLoop if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.expect_loop_expr().into())
            }
            SyntaxKind::TerminalWhile if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.expect_while_expr().into())
            }
            SyntaxKind::TerminalFor if lbrace_allowed == LbraceAllowed::Allow => {
                Ok(self.expect_for_expr().into())
            }
            SyntaxKind::TerminalOr | SyntaxKind::TerminalOrOr
                if lbrace_allowed == LbraceAllowed::Allow =>
            {
                Ok(self.expect_closure_expr().into())
            }
            _ => {
                // TODO(yuval): report to diagnostics.
                Err(TryParseFailure::SkipToken)
            }
        }
    }

    /// Returns a GreenId of a node with an ExprPath|ExprParenthesized|ExprTuple kind, or
    /// TryParseFailure if such an expression can't be parsed.
    fn try_parse_type_expr(&mut self) -> TryParseResult<ExprGreen<'a>> {
        // TODO(yuval): support paths starting with "::".
        match self.peek().kind {
            SyntaxKind::TerminalAt => {
                let op = self.take::<TerminalAt<'_>>().into();
                let expr = self.parse_type_expr();
                Ok(ExprUnary::new_green(self.db, op, expr).into())
            }
            SyntaxKind::TerminalAnd | SyntaxKind::TerminalAndAnd => {
                self.unglue_andand_for_unary();
                let op = self.take::<TerminalAnd<'_>>().into();
                let expr = self.parse_type_expr();
                Ok(ExprUnary::new_green(self.db, op, expr).into())
            }
            SyntaxKind::TerminalIdentifier | SyntaxKind::TerminalDollar => {
                Ok(self.parse_type_path().into())
            }
            SyntaxKind::TerminalLParen => Ok(self.expect_type_tuple_expr()),
            SyntaxKind::TerminalLBrack => Ok(self.expect_type_fixed_size_array_expr()),
            _ => {
                // TODO(yuval): report to diagnostics.
                Err(TryParseFailure::SkipToken)
            }
        }
    }

    /// Returns a GreenId of a node with an ExprPath|ExprParenthesized|ExprTuple kind, or
    /// ExprMissing if such an expression can't be parsed.
    fn parse_type_expr(&mut self) -> ExprGreen<'a> {
        match self.try_parse_type_expr() {
            Ok(expr) => expr,
            Err(_) => self
                .create_and_report_missing::<Expr<'_>>(ParserDiagnosticKind::MissingTypeExpression),
        }
    }

    /// Assumes the current token is LBrace.
    /// Expected pattern: `\{<StructArgList>\}`
    fn expect_struct_ctor_argument_list_braced(&mut self) -> StructArgListBracedGreen<'a> {
        let lbrace = self.take::<TerminalLBrace<'_>>();
        let arg_list = StructArgList::new_green(
            self.db,
            &self.parse_separated_list::<StructArg<'_>, TerminalComma<'_>, StructArgListElementOrSeparatorGreen<'_>>(
                Self::try_parse_struct_ctor_argument,
                is_of_kind!(rparen, block, rbrace, module_item_kw),
                "struct constructor argument",
            ),
        );
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();

        StructArgListBraced::new_green(self.db, lbrace, arg_list, rbrace)
    }

    /// Assumes the current token is LParen.
    /// Expected pattern: `<ArgListParenthesized>`
    fn expect_function_call(&mut self, path: ExprPathGreen<'a>) -> ExprFunctionCallGreen<'a> {
        let func_name = path;
        let parenthesized_args = self.expect_parenthesized_argument_list();
        ExprFunctionCall::new_green(self.db, func_name, parenthesized_args)
    }

    /// Assumes the current token is TerminalNot.
    /// Expected pattern: `!<WrappedArgList>`
    fn expect_macro_call(&mut self, path: ExprPathGreen<'a>) -> ExprInlineMacroGreen<'a> {
        let bang = self.take::<TerminalNot<'_>>();
        let macro_name = path;
        let token_tree_node = self.parse_token_tree_node();
        ExprInlineMacro::new_green(self.db, macro_name, bang, token_tree_node)
    }

    /// Either parses a leaf of the tree (i.e. any non-parenthesis token) or an inner node (i.e. a
    /// parenthesized stream of tokens).
    fn parse_token_tree(&mut self) -> TokenTreeGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalLBrace
            | SyntaxKind::TerminalLParen
            | SyntaxKind::TerminalLBrack => self.parse_token_tree_node().into(),
            SyntaxKind::TerminalDollar => {
                let dollar: TerminalDollarGreen<'_> = self.take::<TerminalDollar<'_>>();
                match self.peek().kind {
                    SyntaxKind::TerminalLParen => {
                        let lparen = self.take::<TerminalLParen<'_>>();
                        let elements = TokenList::new_green(self.db, &self.parse_token_list());
                        let rparen = self.parse_token::<TerminalRParen<'_>>();
                        let separator: OptionTerminalCommaGreen<'_> = match self.peek().kind {
                            SyntaxKind::TerminalComma => self.take::<TerminalComma<'_>>().into(),
                            _ => OptionTerminalCommaEmpty::new_green(self.db).into(),
                        };
                        let operator = match self.peek().kind {
                            SyntaxKind::TerminalQuestionMark => {
                                self.take::<TerminalQuestionMark<'_>>().into()
                            }
                            SyntaxKind::TerminalPlus => self.take::<TerminalPlus<'_>>().into(),
                            SyntaxKind::TerminalMul => self.take::<TerminalMul<'_>>().into(),
                            _ => unreachable!(),
                        };
                        TokenTreeRepetition::new_green(
                            self.db, dollar, lparen, elements, rparen, separator, operator,
                        )
                        .into()
                    }
                    SyntaxKind::TerminalIdentifier => {
                        let identifier = self.take::<TerminalIdentifier<'_>>();
                        TokenTreeParam::new_green(self.db, dollar, identifier).into()
                    }
                    _ => self.parse_token_tree_leaf().into(),
                }
            }
            _ => self.parse_token_tree_leaf().into(),
        }
    }

    fn parse_token_tree_leaf(&mut self) -> TokenTreeLeafGreen<'a> {
        let token_node = self.take_token_node();
        TokenTreeLeaf::new_green(self.db, token_node)
    }

    fn parse_token_tree_node(&mut self) -> TokenTreeNodeGreen<'a> {
        let wrapped_token_tree = match self.peek().kind {
            SyntaxKind::TerminalLBrace => self
                .expect_wrapped_token_tree::<TerminalLBrace<'_>, TerminalRBrace<'_>, _, _>(
                    BracedTokenTree::new_green,
                )
                .into(),
            SyntaxKind::TerminalLParen => self
                .expect_wrapped_token_tree::<TerminalLParen<'_>, TerminalRParen<'_>, _, _>(
                    ParenthesizedTokenTree::new_green,
                )
                .into(),
            SyntaxKind::TerminalLBrack => self
                .expect_wrapped_token_tree::<TerminalLBrack<'_>, TerminalRBrack<'_>, _, _>(
                    BracketedTokenTree::new_green,
                )
                .into(),
            _ => {
                return self.create_and_report_missing::<TokenTreeNode<'_>>(
                    ParserDiagnosticKind::MissingWrappedArgList,
                );
            }
        };
        TokenTreeNode::new_green(self.db, wrapped_token_tree)
    }

    /// Assumes the current token is LTerminal.
    /// Expected pattern: `[LTerminal](<expr>,)*<expr>?[RTerminal]`
    /// Gets `new_green` a green id node builder for the list of the requested type, applies it to
    /// the parsed list and returns the result.
    fn expect_wrapped_token_tree<
        LTerminal: syntax::node::Terminal<'a>,
        RTerminal: syntax::node::Terminal<'a>,
        ListGreen,
        NewGreen: Fn(&'a dyn Database, LTerminal::Green, TokenListGreen<'a>, RTerminal::Green) -> ListGreen,
    >(
        &mut self,
        new_green: NewGreen,
    ) -> ListGreen {
        let l_term = self.take::<LTerminal>();
        let tokens = self.parse_token_list();
        let r_term: <RTerminal as TypedSyntaxNode<'_>>::Green = self.parse_token::<RTerminal>();
        new_green(self.db, l_term, TokenList::new_green(self.db, &tokens), r_term)
    }

    fn parse_token_list(&mut self) -> Vec<TokenTreeGreen<'a>> {
        let mut tokens: Vec<TokenTreeGreen<'_>> = vec![];
        while !matches!(
            self.peek().kind,
            SyntaxKind::TerminalRParen
                | SyntaxKind::TerminalRBrace
                | SyntaxKind::TerminalRBrack
                | SyntaxKind::TerminalEndOfFile
        ) {
            tokens.push(self.parse_token_tree());
        }
        tokens
    }

    /// Takes a TokenNode according to the current SyntaxKind.
    fn take_token_node(&mut self) -> TokenNodeGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalIdentifier => self.take::<TerminalIdentifier<'_>>().into(),
            SyntaxKind::TerminalLiteralNumber => self.take::<TerminalLiteralNumber<'_>>().into(),
            SyntaxKind::TerminalShortString => self.take::<TerminalShortString<'_>>().into(),
            SyntaxKind::TerminalString => self.take::<TerminalString<'_>>().into(),
            SyntaxKind::TerminalAs => self.take::<TerminalAs<'_>>().into(),
            SyntaxKind::TerminalConst => self.take::<TerminalConst<'_>>().into(),
            SyntaxKind::TerminalElse => self.take::<TerminalElse<'_>>().into(),
            SyntaxKind::TerminalEnum => self.take::<TerminalEnum<'_>>().into(),
            SyntaxKind::TerminalExtern => self.take::<TerminalExtern<'_>>().into(),
            SyntaxKind::TerminalFalse => self.take::<TerminalFalse<'_>>().into(),
            SyntaxKind::TerminalFunction => self.take::<TerminalFunction<'_>>().into(),
            SyntaxKind::TerminalIf => self.take::<TerminalIf<'_>>().into(),
            SyntaxKind::TerminalWhile => self.take::<TerminalWhile<'_>>().into(),
            SyntaxKind::TerminalFor => self.take::<TerminalFor<'_>>().into(),
            SyntaxKind::TerminalLoop => self.take::<TerminalLoop<'_>>().into(),
            SyntaxKind::TerminalImpl => self.take::<TerminalImpl<'_>>().into(),
            SyntaxKind::TerminalImplicits => self.take::<TerminalImplicits<'_>>().into(),
            SyntaxKind::TerminalLet => self.take::<TerminalLet<'_>>().into(),
            SyntaxKind::TerminalMatch => self.take::<TerminalMatch<'_>>().into(),
            SyntaxKind::TerminalModule => self.take::<TerminalModule<'_>>().into(),
            SyntaxKind::TerminalMut => self.take::<TerminalMut<'_>>().into(),
            SyntaxKind::TerminalNoPanic => self.take::<TerminalNoPanic<'_>>().into(),
            SyntaxKind::TerminalOf => self.take::<TerminalOf<'_>>().into(),
            SyntaxKind::TerminalRef => self.take::<TerminalRef<'_>>().into(),
            SyntaxKind::TerminalContinue => self.take::<TerminalContinue<'_>>().into(),
            SyntaxKind::TerminalReturn => self.take::<TerminalReturn<'_>>().into(),
            SyntaxKind::TerminalBreak => self.take::<TerminalBreak<'_>>().into(),
            SyntaxKind::TerminalStruct => self.take::<TerminalStruct<'_>>().into(),
            SyntaxKind::TerminalTrait => self.take::<TerminalTrait<'_>>().into(),
            SyntaxKind::TerminalTrue => self.take::<TerminalTrue<'_>>().into(),
            SyntaxKind::TerminalType => self.take::<TerminalType<'_>>().into(),
            SyntaxKind::TerminalUse => self.take::<TerminalUse<'_>>().into(),
            SyntaxKind::TerminalPub => self.take::<TerminalPub<'_>>().into(),
            SyntaxKind::TerminalAnd => self.take::<TerminalAnd<'_>>().into(),
            SyntaxKind::TerminalAndAnd => self.take::<TerminalAndAnd<'_>>().into(),
            SyntaxKind::TerminalArrow => self.take::<TerminalArrow<'_>>().into(),
            SyntaxKind::TerminalAt => self.take::<TerminalAt<'_>>().into(),
            SyntaxKind::TerminalBadCharacters => self.take::<TerminalBadCharacters<'_>>().into(),
            SyntaxKind::TerminalColon => self.take::<TerminalColon<'_>>().into(),
            SyntaxKind::TerminalColonColon => self.take::<TerminalColonColon<'_>>().into(),
            SyntaxKind::TerminalComma => self.take::<TerminalComma<'_>>().into(),
            SyntaxKind::TerminalDiv => self.take::<TerminalDiv<'_>>().into(),
            SyntaxKind::TerminalDivEq => self.take::<TerminalDivEq<'_>>().into(),
            SyntaxKind::TerminalDollar => self.take::<TerminalDollar<'_>>().into(),
            SyntaxKind::TerminalDot => self.take::<TerminalDot<'_>>().into(),
            SyntaxKind::TerminalDotDot => self.take::<TerminalDotDot<'_>>().into(),
            SyntaxKind::TerminalDotDotEq => self.take::<TerminalDotDotEq<'_>>().into(),
            SyntaxKind::TerminalEndOfFile => self.take::<TerminalEndOfFile<'_>>().into(),
            SyntaxKind::TerminalEq => self.take::<TerminalEq<'_>>().into(),
            SyntaxKind::TerminalEqEq => self.take::<TerminalEqEq<'_>>().into(),
            SyntaxKind::TerminalGE => self.take::<TerminalGE<'_>>().into(),
            SyntaxKind::TerminalGT => self.take::<TerminalGT<'_>>().into(),
            SyntaxKind::TerminalHash => self.take::<TerminalHash<'_>>().into(),
            SyntaxKind::TerminalLBrace => self.take::<TerminalLBrace<'_>>().into(),
            SyntaxKind::TerminalLBrack => self.take::<TerminalLBrack<'_>>().into(),
            SyntaxKind::TerminalLE => self.take::<TerminalLE<'_>>().into(),
            SyntaxKind::TerminalLParen => self.take::<TerminalLParen<'_>>().into(),
            SyntaxKind::TerminalLT => self.take::<TerminalLT<'_>>().into(),
            SyntaxKind::TerminalMatchArrow => self.take::<TerminalMatchArrow<'_>>().into(),
            SyntaxKind::TerminalMinus => self.take::<TerminalMinus<'_>>().into(),
            SyntaxKind::TerminalMinusEq => self.take::<TerminalMinusEq<'_>>().into(),
            SyntaxKind::TerminalMod => self.take::<TerminalMod<'_>>().into(),
            SyntaxKind::TerminalModEq => self.take::<TerminalModEq<'_>>().into(),
            SyntaxKind::TerminalMul => self.take::<TerminalMul<'_>>().into(),
            SyntaxKind::TerminalMulEq => self.take::<TerminalMulEq<'_>>().into(),
            SyntaxKind::TerminalNeq => self.take::<TerminalNeq<'_>>().into(),
            SyntaxKind::TerminalNot => self.take::<TerminalNot<'_>>().into(),
            SyntaxKind::TerminalBitNot => self.take::<TerminalBitNot<'_>>().into(),
            SyntaxKind::TerminalOr => self.take::<TerminalOr<'_>>().into(),
            SyntaxKind::TerminalOrOr => self.take::<TerminalOrOr<'_>>().into(),
            SyntaxKind::TerminalPlus => self.take::<TerminalPlus<'_>>().into(),
            SyntaxKind::TerminalPlusEq => self.take::<TerminalPlusEq<'_>>().into(),
            SyntaxKind::TerminalQuestionMark => self.take::<TerminalQuestionMark<'_>>().into(),
            SyntaxKind::TerminalRBrace => self.take::<TerminalRBrace<'_>>().into(),
            SyntaxKind::TerminalRBrack => self.take::<TerminalRBrack<'_>>().into(),
            SyntaxKind::TerminalRParen => self.take::<TerminalRParen<'_>>().into(),
            SyntaxKind::TerminalSemicolon => self.take::<TerminalSemicolon<'_>>().into(),
            SyntaxKind::TerminalUnderscore => self.take::<TerminalUnderscore<'_>>().into(),
            SyntaxKind::TerminalXor => self.take::<TerminalXor<'_>>().into(),
            other => unreachable!("Unexpected token kind: {other:?}"),
        }
    }
    /// Returns a GreenId of a node with an ArgListParenthesized|ArgListBracketed|ArgListBraced kind
    /// or TryParseFailure if such an argument list can't be parsed.
    pub(crate) fn parse_wrapped_arg_list(&mut self) -> WrappedArgListGreen<'a> {
        match self.peek().kind {
            SyntaxKind::TerminalLParen => self
                .expect_wrapped_argument_list::<TerminalLParen<'_>, TerminalRParen<'_>, _, _>(
                    ArgListParenthesized::new_green,
                )
                .into(),
            SyntaxKind::TerminalLBrack => self
                .expect_wrapped_argument_list::<TerminalLBrack<'_>, TerminalRBrack<'_>, _, _>(
                    ArgListBracketed::new_green,
                )
                .into(),
            SyntaxKind::TerminalLBrace => self
                .expect_wrapped_argument_list::<TerminalLBrace<'_>, TerminalRBrace<'_>, _, _>(
                    ArgListBraced::new_green,
                )
                .into(),
            _ => self.create_and_report_missing::<WrappedArgList<'_>>(
                ParserDiagnosticKind::MissingWrappedArgList,
            ),
        }
    }

    /// Assumes the current token is LTerminal.
    /// Expected pattern: `[LTerminal](<expr>,)*<expr>?[RTerminal]`
    /// Gets `new_green` a green id node builder for the list of the requested type, applies it to
    /// the parsed list and returns the result.
    fn expect_wrapped_argument_list<
        LTerminal: syntax::node::Terminal<'a>,
        RTerminal: syntax::node::Terminal<'a>,
        ListGreen,
        NewGreen: Fn(&'a dyn Database, LTerminal::Green, ArgListGreen<'a>, RTerminal::Green) -> ListGreen,
    >(
        &mut self,
        new_green: NewGreen,
    ) -> ListGreen {
        let l_term = self.take::<LTerminal>();
        let exprs: Vec<ArgListElementOrSeparatorGreen<'_>> = self
            .parse_separated_list::<Arg<'_>, TerminalComma<'_>, ArgListElementOrSeparatorGreen<'_>>(
                Self::try_parse_function_argument,
                is_of_kind!(rparen, rbrace, rbrack, block, module_item_kw),
                "argument",
            );
        let r_term: <RTerminal as TypedSyntaxNode<'_>>::Green = self.parse_token::<RTerminal>();
        new_green(self.db, l_term, ArgList::new_green(self.db, &exprs), r_term)
    }

    /// Assumes the current token is LParen.
    /// Expected pattern: `\(<ArgList>\)`
    fn expect_parenthesized_argument_list(&mut self) -> ArgListParenthesizedGreen<'a> {
        self.expect_wrapped_argument_list::<TerminalLParen<'_>, TerminalRParen<'_>, _, _>(
            ArgListParenthesized::new_green,
        )
    }

    /// Tries to parse parenthesized argument list.
    /// Expected pattern: `\(<ArgList>\)`
    fn try_parse_parenthesized_argument_list(&mut self) -> OptionArgListParenthesizedGreen<'a> {
        if self.peek().kind == SyntaxKind::TerminalLParen {
            self.expect_parenthesized_argument_list().into()
        } else {
            OptionArgListParenthesizedEmpty::new_green(self.db).into()
        }
    }

    /// Parses a function call's argument, which contains possibly modifiers, and an argument
    /// clause.
    fn try_parse_function_argument(&mut self) -> TryParseResult<ArgGreen<'a>> {
        let modifiers_list = self.parse_modifier_list();
        let arg_clause = self.try_parse_argument_clause();
        match arg_clause {
            Ok(arg_clause) => {
                let modifiers = ModifierList::new_green(self.db, &modifiers_list);
                Ok(Arg::new_green(self.db, modifiers, arg_clause))
            }
            Err(_) if !modifiers_list.is_empty() => {
                let modifiers = ModifierList::new_green(self.db, &modifiers_list);
                let arg_clause = ArgClauseUnnamed::new_green(self.db, self.parse_expr()).into();
                Ok(Arg::new_green(self.db, modifiers, arg_clause))
            }
            Err(err) => Err(err),
        }
    }

    /// Parses a function call's argument, which is an expression with or without the name
    /// of the argument.
    ///
    /// Possible patterns:
    /// * `<Expr>` (unnamed).
    /// * `<Identifier>: <Expr>` (named).
    /// * `:<Identifier>` (Field init shorthand - syntactic sugar for `a: a`).
    fn try_parse_argument_clause(&mut self) -> TryParseResult<ArgClauseGreen<'a>> {
        if self.peek().kind == SyntaxKind::TerminalColon {
            let colon = self.take::<TerminalColon<'_>>();
            let name = self.parse_identifier();
            return Ok(ArgClauseFieldInitShorthand::new_green(
                self.db,
                colon,
                ExprFieldInitShorthand::new_green(self.db, name),
            )
            .into());
        }

        // Read an expression.
        let value = self.try_parse_expr()?;
        // If the next token is `:` and the expression is an identifier, this is the argument's
        // name.
        Ok(
            if self.peek().kind == SyntaxKind::TerminalColon
                && let Some(argname) = self.try_extract_identifier(value)
            {
                let colon = self.take::<TerminalColon<'_>>();
                let expr = self.parse_expr();
                ArgClauseNamed::new_green(self.db, argname, colon, expr).into()
            } else {
                ArgClauseUnnamed::new_green(self.db, value).into()
            },
        )
    }

    /// If the given `expr` is a simple identifier, returns the corresponding green node.
    /// Otherwise, returns `TryParseFailure`.
    fn try_extract_identifier(&self, expr: ExprGreen<'a>) -> Option<TerminalIdentifierGreen<'a>> {
        // Check that `expr` is `ExprPath`.
        let GreenNode {
            kind: SyntaxKind::ExprPath,
            details: GreenNodeDetails::Node { children: children0, .. },
        } = expr.0.long(self.db)
        else {
            return None;
        };

        // Extract ExprPathInner
        let [_dollar, path_inner] = children0[..] else {
            return None;
        };

        let GreenNode {
            kind: SyntaxKind::ExprPathInner,
            details: GreenNodeDetails::Node { children: children1, .. },
        } = path_inner.long(self.db)
        else {
            return None;
        };

        // Check that it has one child.
        let [path_segment] = children1[..] else {
            return None;
        };

        // Check that `path_segment` is `PathSegmentSimple`.
        let GreenNode {
            kind: SyntaxKind::PathSegmentSimple,
            details: GreenNodeDetails::Node { children: children2, .. },
        } = path_segment.long(self.db)
        else {
            return None;
        };

        // Check that it has one child.
        let [ident] = children2[..] else {
            return None;
        };

        // Check that it is indeed `TerminalIdentifier`.
        let GreenNode { kind: SyntaxKind::TerminalIdentifier, .. } = ident.long(self.db) else {
            return None;
        };

        Some(TerminalIdentifierGreen(ident))
    }

    /// Assumes the current token is LBrace.
    /// Expected pattern: `<StructArgListBraced>`
    fn expect_constructor_call(&mut self, path: ExprPathGreen<'a>) -> ExprStructCtorCallGreen<'a> {
        let ctor_name = path;
        let args = self.expect_struct_ctor_argument_list_braced();
        ExprStructCtorCall::new_green(self.db, ctor_name, args)
    }

    /// Assumes the current token is LParen.
    /// Expected pattern: `\((<expr>,)*<expr>?\)`
    /// Returns a GreenId of a node with kind ExprParenthesized|ExprTuple.
    fn expect_parenthesized_expr(&mut self) -> ExprGreen<'a> {
        let lparen = self.take::<TerminalLParen<'_>>();
        let exprs: Vec<ExprListElementOrSeparatorGreen<'_>> = self
            .parse_separated_list::<Expr<'_>, TerminalComma<'_>, ExprListElementOrSeparatorGreen<'_>>(
                Self::try_parse_expr,
                is_of_kind!(rparen, block, rbrace, module_item_kw),
                "expression",
            );
        let rparen = self.parse_token::<TerminalRParen<'_>>();

        if let [ExprListElementOrSeparatorGreen::Element(expr)] = &exprs[..] {
            // We have exactly one item and no separator --> This is not a tuple.
            ExprParenthesized::new_green(self.db, lparen, *expr, rparen).into()
        } else {
            ExprListParenthesized::new_green(
                self.db,
                lparen,
                ExprList::new_green(self.db, &exprs),
                rparen,
            )
            .into()
        }
    }

    /// Assumes the current token is LParen.
    /// Expected pattern: `\((<type_expr>,)*<type_expr>?\)`
    /// Returns a GreenId of a node with kind ExprTuple.
    fn expect_type_tuple_expr(&mut self) -> ExprGreen<'a> {
        let lparen = self.take::<TerminalLParen<'_>>();
        let exprs: Vec<ExprListElementOrSeparatorGreen<'_>> = self
            .parse_separated_list::<Expr<'_>, TerminalComma<'_>, ExprListElementOrSeparatorGreen<'_>>(
                Self::try_parse_type_expr,
                is_of_kind!(rparen, block, rbrace, module_item_kw),
                "type expression",
            );
        let rparen = self.parse_token::<TerminalRParen<'_>>();
        if let [ExprListElementOrSeparatorGreen::Element(_)] = &exprs[..] {
            self.add_diagnostic(
                ParserDiagnosticKind::MissingToken(SyntaxKind::TokenComma),
                TextSpan::cursor(self.offset),
            );
        }
        ExprListParenthesized::new_green(
            self.db,
            lparen,
            ExprList::new_green(self.db, &exprs),
            rparen,
        )
        .into()
    }

    /// Assumes the current token is LBrack.
    /// Expected pattern: `\[<type_expr>; <expr>\]`.
    /// Returns a GreenId of a node with kind ExprFixedSizeArray.
    fn expect_type_fixed_size_array_expr(&mut self) -> ExprGreen<'a> {
        let lbrack = self.take::<TerminalLBrack<'_>>();
        let exprs: Vec<ExprListElementOrSeparatorGreen<'_>> = self
            .parse_separated_list::<Expr<'_>, TerminalComma<'_>, ExprListElementOrSeparatorGreen<'_>>(
                Self::try_parse_type_expr,
                is_of_kind!(rbrack, semicolon),
                "type expression",
            );
        let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
        let size_expr = self.parse_expr();
        let fixed_size_array_size =
            FixedSizeArraySize::new_green(self.db, semicolon, size_expr).into();
        let rbrack = self.parse_token::<TerminalRBrack<'_>>();
        ExprFixedSizeArray::new_green(
            self.db,
            lbrack,
            ExprList::new_green(self.db, &exprs),
            fixed_size_array_size,
            rbrack,
        )
        .into()
    }

    /// Assumes the current token is DotDot.
    /// Expected pattern: `\.\.<Expr>`
    fn expect_struct_argument_tail(&mut self) -> StructArgTailGreen<'a> {
        let dotdot = self.take::<TerminalDotDot<'_>>(); // ..
        // TODO(yuval): consider changing this to SimpleExpr once it exists.
        let expr = self.parse_expr();
        StructArgTail::new_green(self.db, dotdot, expr)
    }

    // For the similar syntax in Rust, see
    // https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax.
    /// Like parse_argument, but also allows a struct-arg-tail, e.g. 'let s2 = S{"s2", ..s1};'
    /// Returns a GreenId of a node with kind StructArgSingle|StructArgTail.
    fn try_parse_struct_ctor_argument(&mut self) -> TryParseResult<StructArgGreen<'a>> {
        match self.peek().kind {
            SyntaxKind::TerminalDotDot => Ok(self.expect_struct_argument_tail().into()),
            _ => self.try_parse_argument_single().map(|arg| arg.into()),
        }
    }

    /// Returns a GreenId of a node with kind StructArgExpr or OptionStructArgExprEmpty if an
    /// argument expression `(":<value>")` can't be parsed.
    fn parse_option_struct_arg_expression(&mut self) -> OptionStructArgExprGreen<'a> {
        if self.peek().kind == SyntaxKind::TerminalColon {
            let colon = self.take::<TerminalColon<'_>>();
            let value = self.parse_expr();
            StructArgExpr::new_green(self.db, colon, value).into()
        } else {
            OptionStructArgExprEmpty::new_green(self.db).into()
        }
    }

    /// Returns a GreenId of a node with kind OptionExprClause or OptionExprClauseEmpty if an
    /// argument expression `("Expr")` can't be parsed.
    fn parse_option_expression_clause(&mut self) -> OptionExprClauseGreen<'a> {
        if self.peek().kind == SyntaxKind::TerminalSemicolon {
            OptionExprClauseEmpty::new_green(self.db).into()
        } else {
            let value = self.parse_expr();
            ExprClause::new_green(self.db, value).into()
        }
    }

    /// Returns a GreenId of a node with kind StructArgSingle.
    fn try_parse_argument_single(&mut self) -> TryParseResult<StructArgSingleGreen<'a>> {
        let identifier = self.try_parse_identifier()?;
        let struct_arg_expr = self.parse_option_struct_arg_expression(); // :<expr>
        Ok(StructArgSingle::new_green(self.db, identifier, struct_arg_expr))
    }

    /// Returns a GreenId of a node with kind ExprBlock.
    fn parse_block(&mut self) -> ExprBlockGreen<'a> {
        let skipped_tokens = self.skip_until(is_of_kind!(rbrace, lbrace, module_item_kw, block));

        if let Err(SkippedError(span)) = skipped_tokens {
            self.add_diagnostic(
                ParserDiagnosticKind::SkippedElement { element_name: "'{'".into() },
                span,
            );
        }

        let is_rbrace_or_top_level = is_of_kind!(rbrace, module_item_kw);
        if is_rbrace_or_top_level(self.peek().kind) {
            return ExprBlock::new_green(
                self.db,
                self.create_and_report_missing_terminal::<TerminalLBrace<'_>>(),
                StatementList::new_green(self.db, &[]),
                TerminalRBrace::missing(self.db),
            );
        }
        // Don't report diagnostic if one has already been reported.
        let lbrace = self.parse_token_ex::<TerminalLBrace<'_>>(skipped_tokens.is_ok());
        let statements = StatementList::new_green(
            self.db,
            &self.parse_list(
                Self::try_parse_statement,
                is_of_kind!(rbrace, module_item_kw),
                "statement",
            ),
        );
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
        ExprBlock::new_green(self.db, lbrace, statements, rbrace)
    }

    /// Assumes the current token is `Match`.
    /// Expected pattern: `match <expr> \{<MatchArm>*\}`
    fn expect_match_expr(&mut self) -> ExprMatchGreen<'a> {
        let match_kw = self.take::<TerminalMatch<'_>>();
        let expr =
            self.parse_expr_limited(MAX_PRECEDENCE, LbraceAllowed::Forbid, AndLetBehavior::Simple);
        let lbrace = self.parse_token::<TerminalLBrace<'_>>();
        let arms = MatchArms::new_green(
            self.db,
            &self
                .parse_separated_list::<MatchArm<'_>, TerminalComma<'_>, MatchArmsElementOrSeparatorGreen<'_>>(
                    Self::try_parse_match_arm,
                    is_of_kind!(block, rbrace, module_item_kw),
                    "match arm",
                ),
        );
        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
        ExprMatch::new_green(self.db, match_kw, expr, lbrace, arms, rbrace)
    }

    /// Assumes the current token is `If`.
    fn expect_if_expr(&mut self) -> ExprIfGreen<'a> {
        let if_kw = self.take::<TerminalIf<'a>>();

        let conditions = self.parse_condition_list();
        let if_block = self.parse_block();
        let else_clause = if self.peek().kind == SyntaxKind::TerminalElse {
            let else_kw = self.take::<TerminalElse<'a>>();
            let else_block_or_if = if self.peek().kind == SyntaxKind::TerminalIf {
                self.expect_if_expr().into()
            } else {
                self.parse_block().into()
            };
            ElseClause::new_green(self.db, else_kw, else_block_or_if).into()
        } else {
            OptionElseClauseEmpty::new_green(self.db).into()
        };
        ExprIf::new_green(self.db, if_kw, conditions, if_block, else_clause)
    }

    /// If `condition` is a [ConditionExpr] of the form `<expr> <op> <expr>`, returns the operator's
    /// kind.
    /// Otherwise, returns `None`.
    fn get_binary_operator(&self, condition: ConditionGreen<'_>) -> Option<SyntaxKind> {
        let condition_expr_green = condition.0.long(self.db);
        require(condition_expr_green.kind == SyntaxKind::ConditionExpr)?;

        let expr_binary_green = condition_expr_green.children()[0].long(self.db);
        require(expr_binary_green.kind == SyntaxKind::ExprBinary)?;

        Some(expr_binary_green.children()[1].long(self.db).kind)
    }

    /// Parses a conjunction of conditions of the form `<condition> && <condition> && ...`,
    /// where each condition is either `<expr>` or `let <pattern> = <expr>`.
    ///
    /// Assumes the next expected token (after the condition list) is `{`. This assumption is used
    /// in case of an error.
    fn parse_condition_list(&mut self) -> ConditionListAndGreen<'a> {
        let and_and_precedence = get_post_operator_precedence(SyntaxKind::TerminalAndAnd).unwrap();

        let start_offset = self.offset.add_width(self.current_width);
        let condition = self.parse_condition_expr(false);
        let mut conditions: Vec<ConditionListAndElementOrSeparatorGreen<'_>> =
            vec![condition.into()];

        // If there is more than one condition, check that the first condition does not have a
        // precedence lower than `&&`.
        if self.peek().kind == SyntaxKind::TerminalAndAnd
            && let Some(op) = self.get_binary_operator(condition)
            && let Some(precedence) = get_post_operator_precedence(op)
            && precedence > and_and_precedence
        {
            let offset = self.offset.add_width(self.current_width - self.last_trivia_length);
            self.add_diagnostic(
                ParserDiagnosticKind::LowPrecedenceOperatorInIfLet { op },
                TextSpan::new(start_offset, offset),
            );
        }

        while self.peek().kind == SyntaxKind::TerminalAndAnd {
            let and_and = self.take::<TerminalAndAnd<'a>>();
            conditions.push(and_and.into());

            let condition = self.parse_condition_expr(true);
            conditions.push(condition.into());
        }

        let peek_item = self.peek();
        if let Some(op_precedence) = get_post_operator_precedence(peek_item.kind)
            && op_precedence > and_and_precedence
        {
            self.add_diagnostic(
                ParserDiagnosticKind::LowPrecedenceOperatorInIfLet { op: peek_item.kind },
                TextSpan::cursor(self.offset.add_width(self.current_width)),
            );
            // Skip the rest of the tokens until `{`. Don't report additional diagnostics.
            let _ = self.skip_until(is_of_kind!(rbrace, lbrace, module_item_kw, block));
        }
        ConditionListAnd::new_green(self.db, &conditions)
    }

    /// Parses condition exprs of the form `<expr>` or `let <pattern> = <expr>`.
    ///
    /// In the case of `let <pattern> = <expr>`, the parser will stop at the first `&&` token
    /// (which is not inside parenthesis).
    /// If `stop_at_and` is true, this will also be the case for `<expr>`.
    fn parse_condition_expr(&mut self, stop_at_and: bool) -> ConditionGreen<'a> {
        let and_and_precedence = get_post_operator_precedence(SyntaxKind::TerminalAndAnd).unwrap();
        if self.peek().kind == SyntaxKind::TerminalLet {
            let let_kw = self.take::<TerminalLet<'a>>();
            let pattern_list = self
            .parse_separated_list_inner::<Pattern<'_>, TerminalOr<'_>, PatternListOrElementOrSeparatorGreen<'_>>(
                Self::try_parse_pattern,
                is_of_kind!(eq),
                "pattern",
                Some(ParserDiagnosticKind::DisallowedTrailingSeparatorOr),
            );

            let pattern_list_green = if pattern_list.is_empty() {
                self.create_and_report_missing::<PatternListOr<'_>>(
                    ParserDiagnosticKind::MissingPattern,
                )
            } else {
                PatternListOr::new_green(self.db, &pattern_list)
            };
            let eq = self.parse_token::<TerminalEq<'a>>();
            let expr: ExprGreen<'_> = self.parse_expr_limited(
                and_and_precedence,
                LbraceAllowed::Forbid,
                AndLetBehavior::Stop,
            );
            ConditionLet::new_green(self.db, let_kw, pattern_list_green, eq, expr).into()
        } else {
            let condition = self.parse_expr_limited(
                if stop_at_and { and_and_precedence } else { MAX_PRECEDENCE },
                LbraceAllowed::Forbid,
                AndLetBehavior::Stop,
            );
            ConditionExpr::new_green(self.db, condition).into()
        }
    }

    /// Assumes the current token is `Loop`.
    /// Expected pattern: `loop <block>`.
    fn expect_loop_expr(&mut self) -> ExprLoopGreen<'a> {
        let loop_kw = self.take::<TerminalLoop<'a>>();
        let body = self.parse_block();

        ExprLoop::new_green(self.db, loop_kw, body)
    }

    /// Assumes the current token is `While`.
    /// Expected pattern: `while <condition> <block>`.
    fn expect_while_expr(&mut self) -> ExprWhileGreen<'a> {
        let while_kw = self.take::<TerminalWhile<'a>>();
        let conditions = self.parse_condition_list();
        let body = self.parse_block();

        ExprWhile::new_green(self.db, while_kw, conditions, body)
    }

    /// Assumes the current token is `For`.
    /// Expected pattern: `for <pattern> <identifier> <expression> <block>`.
    /// Identifier will be checked to be 'in' in semantics.
    fn expect_for_expr(&mut self) -> ExprForGreen<'a> {
        let for_kw = self.take::<TerminalFor<'a>>();
        let pattern = self.parse_pattern();
        let ident = self.take_raw();
        let in_identifier: TerminalIdentifierGreen<'_> = match ident.text.long(self.db).as_str() {
            "in" => self.add_trivia_to_terminal::<TerminalIdentifier<'_>>(ident),
            _ => {
                self.append_skipped_token_to_pending_trivia(
                    ident,
                    ParserDiagnosticKind::SkippedElement { element_name: "'in'".into() },
                );
                TerminalIdentifier::missing(self.db)
            }
        };
        let expression =
            self.parse_expr_limited(MAX_PRECEDENCE, LbraceAllowed::Forbid, AndLetBehavior::Simple);
        let body = self.parse_block();
        ExprFor::new_green(self.db, for_kw, pattern, in_identifier, expression, body)
    }

    /// Assumes the current token is `|`.
    /// Expected pattern: `| <params> | <ReturnTypeClause> <expression>`.
    fn expect_closure_expr(&mut self) -> ExprClosureGreen<'a> {
        self.unglue::<TerminalOrOr<'_>, TerminalOr<'_>, TerminalOr<'_>>("|", "|");
        let leftor = self.take::<TerminalOr<'a>>();
        let params = self.parse_closure_param_list();
        let rightor = self.parse_token::<TerminalOr<'a>>();
        let params = ClosureParams::new_green(self.db, leftor, params, rightor);
        let mut block_required = self.peek().kind == SyntaxKind::TerminalArrow;

        let return_ty = self.parse_option_return_type_clause();
        let optional_no_panic = if self.peek().kind == SyntaxKind::TerminalNoPanic {
            block_required = true;
            self.take::<TerminalNoPanic<'a>>().into()
        } else {
            OptionTerminalNoPanicEmpty::new_green(self.db).into()
        };
        let expr = if block_required { self.parse_block().into() } else { self.parse_expr() };

        ExprClosure::new_green(self.db, params, return_ty, optional_no_panic, expr)
    }

    /// Assumes the current token is LBrack.
    /// Expected pattern: `\[<expr>; <expr>\]`.
    fn expect_fixed_size_array_expr(&mut self) -> ExprFixedSizeArrayGreen<'a> {
        let lbrack = self.take::<TerminalLBrack<'_>>();
        let exprs: Vec<ExprListElementOrSeparatorGreen<'_>> = self
            .parse_separated_list::<Expr<'_>, TerminalComma<'_>, ExprListElementOrSeparatorGreen<'_>>(
                Self::try_parse_expr,
                is_of_kind!(rbrack, semicolon),
                "expression",
            );
        let size_green = if self.peek().kind == SyntaxKind::TerminalSemicolon {
            let semicolon = self.take::<TerminalSemicolon<'_>>();
            let size = self.parse_expr();
            FixedSizeArraySize::new_green(self.db, semicolon, size).into()
        } else {
            OptionFixedSizeArraySizeEmpty::new_green(self.db).into()
        };
        let rbrack = self.parse_token::<TerminalRBrack<'_>>();
        ExprFixedSizeArray::new_green(
            self.db,
            lbrack,
            ExprList::new_green(self.db, &exprs),
            size_green,
            rbrack,
        )
    }

    /// Returns a GreenId of a node with a MatchArm kind or TryParseFailure if a match arm can't be
    /// parsed.
    pub fn try_parse_match_arm(&mut self) -> TryParseResult<MatchArmGreen<'a>> {
        let pattern_list = self
            .parse_separated_list_inner::<Pattern<'_>, TerminalOr<'_>, PatternListOrElementOrSeparatorGreen<'_>>(
                Self::try_parse_pattern,
                is_of_kind!(match_arrow, rparen, block, rbrace, module_item_kw),
                "pattern",
                Some(ParserDiagnosticKind::DisallowedTrailingSeparatorOr),
            );
        if pattern_list.is_empty() {
            return Err(TryParseFailure::SkipToken);
        }

        let pattern_list_green = PatternListOr::new_green(self.db, &pattern_list);

        let arrow = self.parse_token::<TerminalMatchArrow<'_>>();
        let expr = self.parse_expr();
        Ok(MatchArm::new_green(self.db, pattern_list_green, arrow, expr))
    }

    /// Returns a GreenId of a node with some Pattern kind (see
    /// [syntax::node::ast::Pattern]) or TryParseFailure if a pattern can't be parsed.
    fn try_parse_pattern(&mut self) -> TryParseResult<PatternGreen<'a>> {
        let modifier_list = self.parse_modifier_list();
        if !modifier_list.is_empty() {
            let modifiers = ModifierList::new_green(self.db, &modifier_list);
            let name = self.parse_identifier();
            return Ok(PatternIdentifier::new_green(self.db, modifiers, name).into());
        };

        // TODO(yuval): Support "Or" patterns.
        Ok(match self.peek().kind {
            SyntaxKind::TerminalLiteralNumber => self.take_terminal_literal_number().into(),
            SyntaxKind::TerminalShortString => self.take_terminal_short_string().into(),
            SyntaxKind::TerminalTrue => self.take::<TerminalTrue<'_>>().into(),
            SyntaxKind::TerminalFalse => self.take::<TerminalFalse<'_>>().into(),
            SyntaxKind::TerminalUnderscore => self.take::<TerminalUnderscore<'_>>().into(),
            SyntaxKind::TerminalIdentifier => {
                // TODO(ilya): Consider parsing a single identifier as PatternIdentifier rather
                // then ExprPath.
                let path = self.parse_path();
                match self.peek().kind {
                    SyntaxKind::TerminalLBrace => {
                        let lbrace = self.take::<TerminalLBrace<'_>>();
                        let params = PatternStructParamList::new_green(
                            self.db,
                            &self.parse_separated_list::<
                                PatternStructParam<'_>,
                                TerminalComma<'_>,
                                PatternStructParamListElementOrSeparatorGreen<'_>>
                            (
                                Self::try_parse_pattern_struct_param,
                                is_of_kind!(rparen, block, rbrace, module_item_kw),
                                "struct pattern parameter",
                            ),
                        );
                        let rbrace = self.parse_token::<TerminalRBrace<'_>>();
                        PatternStruct::new_green(self.db, path, lbrace, params, rbrace).into()
                    }
                    SyntaxKind::TerminalLParen => {
                        // Enum pattern.
                        let lparen = self.take::<TerminalLParen<'_>>();
                        let pattern = self.parse_pattern();
                        let rparen = self.parse_token::<TerminalRParen<'_>>();
                        let inner_pattern =
                            PatternEnumInnerPattern::new_green(self.db, lparen, pattern, rparen);
                        PatternEnum::new_green(self.db, path, inner_pattern.into()).into()
                    }
                    _ => {
                        // Check that `expr` is `ExprPath`.
                        let GreenNode {
                            kind: SyntaxKind::ExprPath,
                            details: GreenNodeDetails::Node { children: path_children, .. },
                        } = path.0.long(self.db)
                        else {
                            return Err(TryParseFailure::SkipToken);
                        };

                        // Extract ExprPathInner
                        let [_dollar, path_inner] = path_children[..] else {
                            return Err(TryParseFailure::SkipToken);
                        };

                        let GreenNode {
                            kind: SyntaxKind::ExprPathInner,
                            details: GreenNodeDetails::Node { children: inner_path_children, .. },
                        } = path_inner.long(self.db)
                        else {
                            return Err(TryParseFailure::SkipToken);
                        };

                        // If the path has more than 1 element assume it's a simplified Enum variant
                        // Eg. MyEnum::A(()) ~ MyEnum::A
                        // Multi-element path identifiers aren't allowed, for now this mechanism is
                        // sufficient.
                        match inner_path_children.len() {
                            // 0 => return None, - unreachable
                            1 => path.into(),
                            _ => PatternEnum::new_green(
                                self.db,
                                path,
                                OptionPatternEnumInnerPatternEmpty::new_green(self.db).into(),
                            )
                            .into(),
                        }
                    }
                }
            }
            SyntaxKind::TerminalLParen => {
                let lparen = self.take::<TerminalLParen<'_>>();
                let patterns = PatternList::new_green(self.db,  &self.parse_separated_list::<
                    Pattern<'_>,
                    TerminalComma<'_>,
                    PatternListElementOrSeparatorGreen<'_>>
                (
                    Self::try_parse_pattern,
                    is_of_kind!(rparen, block, rbrace, module_item_kw),
                    "pattern",
                ));
                let rparen = self.parse_token::<TerminalRParen<'_>>();
                PatternTuple::new_green(self.db, lparen, patterns, rparen).into()
            }
            SyntaxKind::TerminalLBrack => {
                let lbrack = self.take::<TerminalLBrack<'_>>();
                let patterns = PatternList::new_green(self.db,  &self.parse_separated_list::<
                    Pattern<'_>,
                    TerminalComma<'_>,
                    PatternListElementOrSeparatorGreen<'_>>
                (
                    Self::try_parse_pattern,
                    is_of_kind!(rbrack, block, rbrace, module_item_kw),
                    "pattern",
                ));
                let rbrack = self.parse_token::<TerminalRBrack<'_>>();
                PatternFixedSizeArray::new_green(self.db, lbrack, patterns, rbrack).into()
            }
            _ => return Err(TryParseFailure::SkipToken),
        })
    }
    /// Returns a GreenId of a node with some Pattern kind (see
    /// [syntax::node::ast::Pattern]).
    fn parse_pattern(&mut self) -> PatternGreen<'a> {
        // If not found, return a missing underscore pattern.
        match self.try_parse_pattern() {
            Ok(pattern) => pattern,
            Err(_) => self.create_and_report_missing_terminal::<TerminalUnderscore<'_>>().into(),
        }
    }

    /// Returns a GreenId of a syntax inside a struct pattern. Example:
    /// `MyStruct { param0, param1: _, .. }`.
    fn try_parse_pattern_struct_param(&mut self) -> TryParseResult<PatternStructParamGreen<'a>> {
        Ok(match self.peek().kind {
            SyntaxKind::TerminalDotDot => self.take::<TerminalDotDot<'_>>().into(),
            _ => {
                let modifier_list = self.parse_modifier_list();
                let name = if modifier_list.is_empty() {
                    self.try_parse_identifier()?
                } else {
                    self.parse_identifier()
                };
                let modifiers = ModifierList::new_green(self.db, &modifier_list);
                if self.peek().kind == SyntaxKind::TerminalColon {
                    let colon = self.take::<TerminalColon<'_>>();
                    let pattern = self.parse_pattern();
                    PatternStructParamWithExpr::new_green(self.db, modifiers, name, colon, pattern)
                        .into()
                } else {
                    PatternIdentifier::new_green(self.db, modifiers, name).into()
                }
            }
        })
    }

    // ------------------------------- Statements -------------------------------

    /// Returns a GreenId of a node with a Statement.* kind (see
    /// [syntax::node::ast::Statement]) or TryParseFailure if a statement can't be parsed.
    pub fn try_parse_statement(&mut self) -> TryParseResult<StatementGreen<'a>> {
        let maybe_attributes = self.try_parse_attribute_list("Statement");
        let (has_attrs, attributes) = match maybe_attributes {
            Ok(attributes) => (true, attributes),
            Err(_) => (false, AttributeList::new_green(self.db, &[])),
        };
        match self.peek().kind {
            SyntaxKind::TerminalLet => {
                let let_kw = self.take::<TerminalLet<'_>>();
                let pattern = self.parse_pattern();
                let type_clause = self.parse_option_type_clause();
                let eq = self.parse_token::<TerminalEq<'_>>();
                let rhs = self.parse_expr();

                // Check if this is a let-else statement.
                let let_else_clause: OptionLetElseClauseGreen<'_> =
                    if self.peek().kind == SyntaxKind::TerminalElse {
                        let else_kw = self.take::<TerminalElse<'_>>();
                        let else_block = self.parse_block();
                        LetElseClause::new_green(self.db, else_kw, else_block).into()
                    } else {
                        OptionLetElseClauseEmpty::new_green(self.db).into()
                    };

                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                Ok(StatementLet::new_green(
                    self.db,
                    attributes,
                    let_kw,
                    pattern,
                    type_clause,
                    eq,
                    rhs,
                    let_else_clause,
                    semicolon,
                )
                .into())
            }
            SyntaxKind::TerminalContinue => {
                let continue_kw = self.take::<TerminalContinue<'_>>();
                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                Ok(StatementContinue::new_green(self.db, attributes, continue_kw, semicolon).into())
            }
            SyntaxKind::TerminalReturn => {
                let return_kw = self.take::<TerminalReturn<'_>>();
                let expr = self.parse_option_expression_clause();
                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                Ok(StatementReturn::new_green(self.db, attributes, return_kw, expr, semicolon)
                    .into())
            }
            SyntaxKind::TerminalBreak => {
                let break_kw = self.take::<TerminalBreak<'_>>();
                let expr = self.parse_option_expression_clause();
                let semicolon = self.parse_token::<TerminalSemicolon<'_>>();
                Ok(StatementBreak::new_green(self.db, attributes, break_kw, expr, semicolon).into())
            }
            SyntaxKind::TerminalConst => {
                let const_kw = self.take::<TerminalConst<'_>>();
                Ok(StatementItem::new_green(
                    self.db,
                    self.expect_item_const(
                        attributes,
                        VisibilityDefault::new_green(self.db).into(),
                        const_kw,
                    )
                    .into(),
                )
                .into())
            }
            SyntaxKind::TerminalUse => Ok(StatementItem::new_green(
                self.db,
                self.expect_item_use(attributes, VisibilityDefault::new_green(self.db).into())
                    .into(),
            )
            .into()),
            SyntaxKind::TerminalType => Ok(StatementItem::new_green(
                self.db,
                self.expect_item_type_alias(
                    attributes,
                    VisibilityDefault::new_green(self.db).into(),
                )
                .into(),
            )
            .into()),
            _ => match self.try_parse_expr() {
                Ok(expr) => {
                    let optional_semicolon = if self.peek().kind == SyntaxKind::TerminalSemicolon {
                        self.take::<TerminalSemicolon<'_>>().into()
                    } else {
                        OptionTerminalSemicolonEmpty::new_green(self.db).into()
                    };
                    Ok(StatementExpr::new_green(self.db, attributes, expr, optional_semicolon)
                        .into())
                }
                Err(_) if has_attrs => Ok(self
                    .skip_taken_node_and_return_missing::<Statement<'_>>(
                        attributes,
                        ParserDiagnosticKind::AttributesWithoutStatement,
                    )),
                Err(err) => Err(err),
            },
        }
    }

    /// Returns a GreenId of a node with kind TypeClause or OptionTypeClauseEmpty if a type clause
    /// can't be parsed.
    fn parse_option_type_clause(&mut self) -> OptionTypeClauseGreen<'a> {
        match self.try_parse_type_clause() {
            Some(green) => green.into(),
            None => OptionTypeClauseEmpty::new_green(self.db).into(),
        }
    }

    /// Parses a type clause of the form: `: <type>`.
    fn parse_type_clause(&mut self, error_recovery: ErrorRecovery) -> TypeClauseGreen<'a> {
        match self.try_parse_type_clause() {
            Some(green) => green,
            None => {
                let res = self.create_and_report_missing::<TypeClause<'_>>(
                    ParserDiagnosticKind::MissingTypeClause,
                );
                self.skip_until(error_recovery.should_stop).ok();
                res
            }
        }
    }
    fn try_parse_type_clause(&mut self) -> Option<TypeClauseGreen<'a>> {
        if self.peek().kind == SyntaxKind::TerminalColon {
            let colon = self.take::<TerminalColon<'_>>();
            let ty = self.parse_type_expr();
            Some(TypeClause::new_green(self.db, colon, ty))
        } else {
            None
        }
    }

    /// Returns a GreenId of a node with kind ReturnTypeClause or OptionReturnTypeClauseEmpty if a
    /// return type clause can't be parsed.
    fn parse_option_return_type_clause(&mut self) -> OptionReturnTypeClauseGreen<'a> {
        if self.peek().kind == SyntaxKind::TerminalArrow {
            let arrow = self.take::<TerminalArrow<'_>>();
            let return_type = self.parse_type_expr();
            ReturnTypeClause::new_green(self.db, arrow, return_type).into()
        } else {
            OptionReturnTypeClauseEmpty::new_green(self.db).into()
        }
    }

    /// Returns a GreenId of a node with kind ImplicitsClause or OptionImplicitsClauseEmpty if a
    /// implicits-clause can't be parsed.
    fn parse_option_implicits_clause(&mut self) -> OptionImplicitsClauseGreen<'a> {
        if self.peek().kind == SyntaxKind::TerminalImplicits {
            let implicits_kw = self.take::<TerminalImplicits<'_>>();
            let lparen = self.parse_token::<TerminalLParen<'_>>();
            let implicits = ImplicitsList::new_green(
                self.db,
                &self.parse_separated_list::<ExprPath<'_>, TerminalComma<'_>, ImplicitsListElementOrSeparatorGreen<'_>>(
                    Self::try_parse_path,
                    // Don't stop at keywords as try_parse_path handles keywords inside it. Otherwise the diagnostic is less accurate.
                    is_of_kind!(rparen, lbrace, rbrace),
                    "implicit type",
                ),
            );
            let rparen = self.parse_token::<TerminalRParen<'_>>();
            ImplicitsClause::new_green(self.db, implicits_kw, lparen, implicits, rparen).into()
        } else {
            OptionImplicitsClauseEmpty::new_green(self.db).into()
        }
    }

    /// Returns a GreenId of a node with kind ParamList.
    fn parse_param_list(&mut self) -> ParamListGreen<'a> {
        ParamList::new_green(
            self.db,
            &self.parse_separated_list::<Param<'_>, TerminalComma<'_>, ParamListElementOrSeparatorGreen<'_>>(
                Self::try_parse_param,
                is_of_kind!(rparen, block, lbrace, rbrace, module_item_kw),
                "parameter",
            ),
        )
    }

    /// Returns a GreenId of a node with kind ClosureParamList.
    fn parse_closure_param_list(&mut self) -> ParamListGreen<'a> {
        ParamList::new_green(
            self.db,
            &self.parse_separated_list::<Param<'_>, TerminalComma<'_>, ParamListElementOrSeparatorGreen<'_>>(
                Self::try_parse_closure_param,
                is_of_kind!(or, block, lbrace, rbrace, module_item_kw),
                "parameter",
            ),
        )
    }

    /// Returns a GreenId of a node with kind Modifier or TryParseFailure if a modifier can't be
    /// parsed.
    fn try_parse_modifier(&mut self) -> Option<ModifierGreen<'a>> {
        match self.peek().kind {
            SyntaxKind::TerminalRef => Some(self.take::<TerminalRef<'_>>().into()),
            SyntaxKind::TerminalMut => Some(self.take::<TerminalMut<'_>>().into()),
            _ => None,
        }
    }

    /// Returns a vector of GreenIds with kind Modifier.
    fn parse_modifier_list(&mut self) -> Vec<ModifierGreen<'a>> {
        let mut modifier_list = vec![];

        while let Some(modifier) = self.try_parse_modifier() {
            modifier_list.push(modifier);
        }
        modifier_list
    }

    /// Returns a GreenId of a node with kind Param or TryParseFailure if a parameter can't be
    /// parsed.
    fn try_parse_param(&mut self) -> TryParseResult<ParamGreen<'a>> {
        let modifier_list = self.parse_modifier_list();
        let name = if modifier_list.is_empty() {
            self.try_parse_identifier()?
        } else {
            // If we had modifiers then the identifier is not optional and can't be '_'.
            self.parse_identifier()
        };

        let type_clause = self
            .parse_type_clause(ErrorRecovery {
                should_stop: is_of_kind!(comma, rparen, module_item_kw),
            })
            .into();
        Ok(Param::new_green(
            self.db,
            ModifierList::new_green(self.db, &modifier_list),
            name,
            type_clause,
        ))
    }

    /// Returns a GreenId of a node with kind Param or TryParseFailure if a parameter can't
    /// be parsed.
    fn try_parse_closure_param(&mut self) -> TryParseResult<ParamGreen<'a>> {
        let modifier_list = self.parse_modifier_list();
        let name = if modifier_list.is_empty() {
            self.try_parse_identifier()?
        } else {
            // If we had modifiers then the identifier is not optional and can't be '_'.
            self.parse_identifier()
        };

        let type_clause = self.parse_option_type_clause();
        Ok(Param::new_green(
            self.db,
            ModifierList::new_green(self.db, &modifier_list),
            name,
            type_clause,
        ))
    }

    /// Returns a GreenId of a node with kind MemberList.
    fn parse_member_list(&mut self) -> MemberListGreen<'a> {
        MemberList::new_green(
            self.db,
            &self.parse_separated_list::<
                Member<'_>,
                TerminalComma<'_>,
                MemberListElementOrSeparatorGreen<'_>,
            >(
                Self::try_parse_member,
                is_of_kind!(rparen, block, lbrace, rbrace, module_item_kw),
                "member or variant",
            ),
        )
    }

    /// Returns a GreenId of a node with kind Member or TryParseFailure if a struct member can't be
    /// parsed.
    fn try_parse_member(&mut self) -> TryParseResult<MemberGreen<'a>> {
        let attributes = self.try_parse_attribute_list("Struct member");
        let visibility = self.parse_visibility();
        let (name, attributes) = match attributes {
            Ok(attributes) => (self.parse_identifier(), attributes),
            Err(_) => (self.try_parse_identifier()?, AttributeList::new_green(self.db, &[])),
        };
        let type_clause = self.parse_type_clause(ErrorRecovery {
            should_stop: is_of_kind!(comma, rbrace, module_item_kw),
        });
        Ok(Member::new_green(self.db, attributes, visibility, name, type_clause))
    }

    /// Returns a GreenId of a node with kind VariantList.
    fn parse_variant_list(&mut self) -> VariantListGreen<'a> {
        VariantList::new_green(
            self.db,
            &self
                .parse_separated_list::<Variant<'_>, TerminalComma<'_>, VariantListElementOrSeparatorGreen<'_>>(
                    Self::try_parse_variant,
                    is_of_kind!(rparen, block, lbrace, rbrace, module_item_kw),
                    "variant",
                ),
        )
    }

    /// Returns a GreenId of a node with kind Variant or TryParseFailure if an enum variant can't be
    /// parsed.
    fn try_parse_variant(&mut self) -> TryParseResult<VariantGreen<'a>> {
        let attributes = self.try_parse_attribute_list("Enum variant");
        let (name, attributes) = match attributes {
            Ok(attributes) => (self.parse_identifier(), attributes),
            Err(_) => (self.try_parse_identifier()?, AttributeList::new_green(self.db, &[])),
        };

        let type_clause = self.parse_option_type_clause();
        Ok(Variant::new_green(self.db, attributes, name, type_clause))
    }

    /// Expected pattern: `<PathSegment>(::<PathSegment>)*`
    /// Returns a GreenId of a node with kind ExprPath.
    fn parse_path(&mut self) -> ExprPathGreen<'a> {
        let dollar = match self.peek().kind {
            SyntaxKind::TerminalDollar => self.take::<TerminalDollar<'_>>().into(),
            _ => OptionTerminalDollarEmpty::new_green(self.db).into(),
        };

        let mut children: Vec<ExprPathInnerElementOrSeparatorGreen<'_>> = vec![];
        loop {
            let (segment, optional_separator) = self.parse_path_segment();
            children.push(segment.into());

            if let Some(separator) = optional_separator {
                children.push(separator.into());
                continue;
            }
            break;
        }

        ExprPath::new_green(self.db, dollar, ExprPathInner::new_green(self.db, &children))
    }
    /// Returns a GreenId of a node with kind ExprPath or TryParseFailure if a path can't be parsed.
    fn try_parse_path(&mut self) -> TryParseResult<ExprPathGreen<'a>> {
        if self.is_peek_identifier_like() {
            Ok(self.parse_path())
        } else {
            Err(TryParseFailure::SkipToken)
        }
    }

    /// Expected pattern: `(<PathSegment<'_>>::)*<PathSegment<'_>>(::){0,1}<GenericArgs>`.
    ///
    /// Returns a GreenId of a node with kind ExprPath.
    fn parse_type_path(&mut self) -> ExprPathGreen<'a> {
        let dollar = match self.peek().kind {
            SyntaxKind::TerminalDollar => self.take::<TerminalDollar<'_>>().into(),
            _ => OptionTerminalDollarEmpty::new_green(self.db).into(),
        };

        let mut children: Vec<ExprPathInnerElementOrSeparatorGreen<'_>> = vec![];
        loop {
            let (segment, optional_separator) = self.parse_type_path_segment();
            children.push(segment.into());

            if let Some(separator) = optional_separator {
                children.push(separator.into());
                continue;
            }
            break;
        }

        ExprPath::new_green(self.db, dollar, ExprPathInner::new_green(self.db, &children))
    }

    /// Returns a PathSegment and an optional separator.
    fn parse_path_segment(
        &mut self,
    ) -> (PathSegmentGreen<'a>, Option<TerminalColonColonGreen<'a>>) {
        let identifier = match self.try_parse_identifier() {
            Ok(identifier) => identifier,
            Err(_) => {
                return (
                    self.create_and_report_missing::<PathSegment<'_>>(
                        ParserDiagnosticKind::MissingPathSegment,
                    ),
                    // TODO(ilya, 10/10/2022): Should we continue parsing the path here?
                    None,
                );
            }
        };
        match self.try_parse_token::<TerminalColonColon<'_>>() {
            Ok(separator) if self.peek().kind == SyntaxKind::TerminalLT => (
                PathSegmentWithGenericArgs::new_green(
                    self.db,
                    identifier,
                    separator.into(),
                    self.expect_generic_args(),
                )
                .into(),
                self.try_parse_token::<TerminalColonColon<'_>>().ok(),
            ),
            optional_separator => {
                (PathSegmentSimple::new_green(self.db, identifier).into(), optional_separator.ok())
            }
        }
    }

    /// Returns a Typed PathSegment or a normal PathSegment.
    /// Additionally returns an optional separators.
    fn parse_type_path_segment(
        &mut self,
    ) -> (PathSegmentGreen<'a>, Option<TerminalColonColonGreen<'a>>) {
        let identifier = match self.try_parse_identifier() {
            Ok(identifier) => identifier,
            Err(_) => {
                return (
                    self.create_and_report_missing::<PathSegment<'_>>(
                        ParserDiagnosticKind::MissingPathSegment,
                    ),
                    // TODO(ilya, 10/10/2022): Should we continue parsing the path here?
                    None,
                );
            }
        };
        match self.try_parse_token::<TerminalColonColon<'_>>() {
            Err(_) if self.peek().kind == SyntaxKind::TerminalLT => (
                PathSegmentWithGenericArgs::new_green(
                    self.db,
                    identifier,
                    OptionTerminalColonColonEmpty::new_green(self.db).into(),
                    self.expect_generic_args(),
                )
                .into(),
                None,
            ),
            // This is here to preserve backwards compatibility.
            // This allows Option::<T> to still work after this change.
            Ok(separator) if self.peek().kind == SyntaxKind::TerminalLT => (
                PathSegmentWithGenericArgs::new_green(
                    self.db,
                    identifier,
                    separator.into(),
                    self.expect_generic_args(),
                )
                .into(),
                self.try_parse_token::<TerminalColonColon<'_>>().ok(),
            ),
            optional_separator => {
                (PathSegmentSimple::new_green(self.db, identifier).into(), optional_separator.ok())
            }
        }
    }

    /// Takes and validates a TerminalLiteralNumber token.
    fn take_terminal_literal_number(&mut self) -> TerminalLiteralNumberGreen<'a> {
        let diag = validate_literal_number(self.peek().text.long(self.db));
        let green = self.take::<TerminalLiteralNumber<'_>>();
        self.add_optional_diagnostic(diag);
        green
    }

    /// Takes and validates a TerminalShortString token.
    fn take_terminal_short_string(&mut self) -> TerminalShortStringGreen<'a> {
        let diag = validate_short_string(self.peek().text.long(self.db));
        let green = self.take::<TerminalShortString<'_>>();
        self.add_optional_diagnostic(diag);
        green
    }

    /// Takes and validates a TerminalString token.
    fn take_terminal_string(&mut self) -> TerminalStringGreen<'a> {
        let diag = validate_string(self.peek().text.long(self.db));
        let green = self.take::<TerminalString<'_>>();
        self.add_optional_diagnostic(diag);
        green
    }

    /// Adds a diagnostic of kind `kind` if provided, at the current offset.
    fn add_optional_diagnostic(&mut self, err: Option<ValidationError>) {
        if let Some(err) = err {
            let span = match err.location {
                ValidationLocation::Full => {
                    TextSpan::new_with_width(self.offset, self.current_width)
                }
                ValidationLocation::After => {
                    TextSpan::cursor(self.offset.add_width(self.current_width))
                }
            };
            self.add_diagnostic(err.kind, span);
        }
    }

    /// Returns a GreenId of a node with an
    /// ExprLiteral|ExprPath|ExprParenthesized|ExprTuple|ExprUnderscore kind, or TryParseFailure if
    /// such an expression can't be parsed.
    fn try_parse_generic_arg(&mut self) -> TryParseResult<GenericArgGreen<'a>> {
        let expr = match self.peek().kind {
            SyntaxKind::TerminalUnderscore => {
                let underscore = self.take::<TerminalUnderscore<'_>>().into();
                return Ok(GenericArgUnnamed::new_green(self.db, underscore).into());
            }
            SyntaxKind::TerminalLiteralNumber => self.take_terminal_literal_number().into(),
            SyntaxKind::TerminalMinus => {
                let op = self.take::<TerminalMinus<'_>>().into();
                let expr = self.parse_token::<TerminalLiteralNumber<'_>>().into();
                ExprUnary::new_green(self.db, op, expr).into()
            }
            SyntaxKind::TerminalShortString => self.take_terminal_short_string().into(),
            SyntaxKind::TerminalTrue => self.take::<TerminalTrue<'_>>().into(),
            SyntaxKind::TerminalFalse => self.take::<TerminalFalse<'_>>().into(),
            SyntaxKind::TerminalLBrace => self.parse_block().into(),
            _ => self.try_parse_type_expr()?,
        };

        // If the next token is `:` and the expression is an identifier, this is the argument's
        // name.
        if self.peek().kind == SyntaxKind::TerminalColon
            && let Some(argname) = self.try_extract_identifier(expr)
        {
            let colon = self.take::<TerminalColon<'_>>();
            let expr = if self.peek().kind == SyntaxKind::TerminalUnderscore {
                self.take::<TerminalUnderscore<'_>>().into()
            } else {
                let expr = self.parse_type_expr();
                GenericArgValueExpr::new_green(self.db, expr).into()
            };
            return Ok(GenericArgNamed::new_green(self.db, argname, colon, expr).into());
        }
        Ok(GenericArgUnnamed::new_green(
            self.db,
            GenericArgValueExpr::new_green(self.db, expr).into(),
        )
        .into())
    }

    /// Assumes the current token is LT.
    /// Expected pattern: `\< <GenericArgList> \>`
    fn expect_generic_args(&mut self) -> GenericArgsGreen<'a> {
        let langle = self.take::<TerminalLT<'_>>();
        let generic_args = GenericArgList::new_green(
            self.db,
            &self.parse_separated_list::<GenericArg<'_>, TerminalComma<'_>, GenericArgListElementOrSeparatorGreen<'_>>(
                Self::try_parse_generic_arg,
                is_of_kind!(rangle, rparen, block, lbrace, rbrace, module_item_kw),
                "generic arg",
            ),
        );
        self.unglue::<TerminalGE<'_>, TerminalGT<'_>, TerminalEq<'_>>(">", "=");
        let rangle = self.parse_token::<TerminalGT<'_>>();
        GenericArgs::new_green(self.db, langle, generic_args, rangle)
    }

    /// Assumes the current token is LT.
    /// Expected pattern: `\< <GenericParamList> \>`
    fn expect_generic_params(&mut self) -> WrappedGenericParamListGreen<'a> {
        let langle = self.take::<TerminalLT<'_>>();
        let generic_params = GenericParamList::new_green(
            self.db,
            &self.parse_separated_list::<GenericParam<'_>, TerminalComma<'_>, GenericParamListElementOrSeparatorGreen<'_>>(
                Self::try_parse_generic_param,
                is_of_kind!(rangle, rparen, block, lbrace, rbrace, module_item_kw),
                "generic param",
            ),
        );
        let rangle = self.parse_token::<TerminalGT<'_>>();
        WrappedGenericParamList::new_green(self.db, langle, generic_params, rangle)
    }

    fn parse_optional_generic_params(&mut self) -> OptionWrappedGenericParamListGreen<'a> {
        if self.peek().kind != SyntaxKind::TerminalLT {
            return OptionWrappedGenericParamListEmpty::new_green(self.db).into();
        }
        self.expect_generic_params().into()
    }

    fn try_parse_generic_param(&mut self) -> TryParseResult<GenericParamGreen<'a>> {
        match self.peek().kind {
            SyntaxKind::TerminalConst => {
                let const_kw = self.take::<TerminalConst<'_>>();
                let name = self.parse_identifier();
                let colon = self.parse_token::<TerminalColon<'_>>();
                let ty = self.parse_type_expr();
                Ok(GenericParamConst::new_green(self.db, const_kw, name, colon, ty).into())
            }
            SyntaxKind::TerminalImpl => {
                let impl_kw = self.take::<TerminalImpl<'_>>();
                let name = self.parse_identifier();
                let colon = self.parse_token::<TerminalColon<'_>>();
                let trait_path = self.parse_type_path();
                let associated_item_constraints = self.parse_optional_associated_item_constraints();
                Ok(GenericParamImplNamed::new_green(
                    self.db,
                    impl_kw,
                    name,
                    colon,
                    trait_path,
                    associated_item_constraints,
                )
                .into())
            }
            SyntaxKind::TerminalPlus => {
                let plus = self.take::<TerminalPlus<'_>>();
                let trait_path = self.parse_type_path();
                let associated_item_constraints = self.parse_optional_associated_item_constraints();
                Ok(GenericParamImplAnonymous::new_green(
                    self.db,
                    plus,
                    trait_path,
                    associated_item_constraints,
                )
                .into())
            }
            SyntaxKind::TerminalMinus => {
                let minus = self.take::<TerminalMinus<'_>>();
                let trait_path = self.parse_type_path();
                Ok(GenericParamNegativeImpl::new_green(self.db, minus, trait_path).into())
            }
            _ => Ok(GenericParamType::new_green(self.db, self.try_parse_identifier()?).into()),
        }
    }

    /// Assumes the current token is LBrack.
    /// Expected pattern: `[ <associated_item_constraints_list> ]>`
    fn expect_associated_item_constraints(&mut self) -> AssociatedItemConstraintsGreen<'a> {
        let lbrack = self.take::<TerminalLBrack<'_>>();
        let associated_item_constraints_list = AssociatedItemConstraintList::new_green(
            self.db,
            &self.parse_separated_list::<AssociatedItemConstraint<'_>, TerminalComma<'_>, AssociatedItemConstraintListElementOrSeparatorGreen<'_>>(
                Self::try_parse_associated_item_constraint,
                is_of_kind!(rbrack,rangle, rparen, block, lbrace, rbrace, module_item_kw),
                "associated type argument",
            ),
        );
        let rangle = self.parse_token::<TerminalRBrack<'_>>();
        AssociatedItemConstraints::new_green(
            self.db,
            lbrack,
            associated_item_constraints_list,
            rangle,
        )
    }

    fn parse_optional_associated_item_constraints(
        &mut self,
    ) -> OptionAssociatedItemConstraintsGreen<'a> {
        if self.peek().kind != SyntaxKind::TerminalLBrack {
            return OptionAssociatedItemConstraintsEmpty::new_green(self.db).into();
        }
        self.expect_associated_item_constraints().into()
    }

    /// Returns a GreenId of a node with kind AssociatedTypeArg or TryParseFailure if an associated
    /// type argument can't be parsed.
    fn try_parse_associated_item_constraint(
        &mut self,
    ) -> TryParseResult<AssociatedItemConstraintGreen<'a>> {
        let ident = self.try_parse_identifier()?;
        let colon = self.parse_token::<TerminalColon<'_>>();
        let ty = self.parse_type_expr();
        Ok(AssociatedItemConstraint::new_green(self.db, ident, colon, ty))
    }

    // ------------------------------- Helpers -------------------------------

    /// Parses a list of elements (without separators), where the elements are parsed using
    /// `try_parse_list_element`.
    /// Returns the list of green ids of the elements.
    ///
    /// `should_stop` is a predicate to decide how to proceed in case an element can't be parsed,
    /// according to the current token. If it returns true, the parsing of the list stops. If it
    /// returns false, the current token is skipped and we try to parse an element again.
    ///
    /// `expected_element` is a description of the expected element.
    fn parse_list<ElementGreen>(
        &mut self,
        try_parse_list_element: fn(&mut Self) -> TryParseResult<ElementGreen>,
        should_stop: fn(SyntaxKind) -> bool,
        expected_element: &str,
    ) -> Vec<ElementGreen> {
        let mut children: Vec<ElementGreen> = Vec::new();
        loop {
            let parse_result = try_parse_list_element(self);
            match parse_result {
                Ok(element_green) => {
                    children.push(element_green);
                }
                Err(err) => {
                    if should_stop(self.peek().kind) {
                        break;
                    }
                    if err == TryParseFailure::SkipToken {
                        self.skip_token(ParserDiagnosticKind::SkippedElement {
                            element_name: expected_element.into(),
                        });
                    }
                }
            }
        }
        children
    }

    /// Parses a list of elements (without separators) that can be prefixed with attributes
    /// (#[...]), where the elements are parsed using `try_parse_list_element`.
    /// Returns the list of green ids of the elements.
    ///
    /// `should_stop` is a predicate to decide how to proceed in case an element can't be parsed,
    /// according to the current token. If it returns true, the parsing of the list stops. If it
    /// returns false, the current token is skipped and we try to parse an element again.
    ///
    /// `expected_element` is a description of the expected element. Note: it should not include
    /// "attribute".
    fn parse_attributed_list<ElementGreen>(
        &mut self,
        try_parse_list_element: fn(&mut Self) -> TryParseResult<ElementGreen>,
        should_stop: fn(SyntaxKind) -> bool,
        expected_element: &'a str,
    ) -> Vec<ElementGreen> {
        self.parse_list::<ElementGreen>(
            try_parse_list_element,
            should_stop,
            &or_an_attribute!(expected_element),
        )
    }

    /// Parses a list of elements with `separator`s, where the elements are parsed using
    /// `try_parse_list_element`. Depending on the value of
    /// `forbid_trailing_separator` the separator may or may not appear in
    /// the end of the list. Returns the list of elements and separators. This list contains
    /// alternating children: [element, separator, element, separator, ...]. Separators may be
    /// missing. The length of the list is either 2 * #elements - 1 or 2 * #elements (a
    /// separator for each element or for each element but the last one).
    ///
    /// `should_stop` is a predicate to decide how to proceed in case an element or a separator
    /// can't be parsed, according to the current token.
    /// When parsing an element:
    /// If it returns true, the parsing of the list stops. If it returns false, the current token
    /// is skipped and we try to parse an element again.
    /// When parsing a separator:
    /// If it returns true, the parsing of the list stops. If it returns false, a missing separator
    /// is added and we continue to try to parse another element (with the same token).
    fn parse_separated_list_inner<
        Element: TypedSyntaxNode<'a>,
        Separator: syntax::node::Terminal<'a>,
        ElementOrSeparatorGreen,
    >(
        &mut self,
        try_parse_list_element: fn(&mut Self) -> TryParseResult<Element::Green>,
        should_stop: fn(SyntaxKind) -> bool,
        expected_element: &'static str,
        forbid_trailing_separator: Option<ParserDiagnosticKind>,
    ) -> Vec<ElementOrSeparatorGreen>
    where
        ElementOrSeparatorGreen: From<Separator::Green> + From<Element::Green>,
    {
        let mut children: Vec<ElementOrSeparatorGreen> = Vec::new();
        loop {
            match try_parse_list_element(self) {
                Err(_) if should_stop(self.peek().kind) => {
                    if let (Some(diagnostic_kind), true) =
                        (forbid_trailing_separator, !children.is_empty())
                    {
                        self.add_diagnostic(diagnostic_kind, TextSpan::cursor(self.offset));
                    }
                    break;
                }
                Err(_) => {
                    self.skip_token(ParserDiagnosticKind::SkippedElement {
                        element_name: expected_element.into(),
                    });
                    continue;
                }
                Ok(element) => {
                    children.push(element.into());
                }
            };

            let separator = match self.try_parse_token::<Separator>() {
                Err(_) if should_stop(self.peek().kind) => {
                    break;
                }
                Err(_) => self.create_and_report_missing::<Separator>(
                    ParserDiagnosticKind::MissingToken(Separator::KIND),
                ),
                Ok(separator) => separator,
            };
            children.push(separator.into());
        }
        children
    }
    /// Calls parse_separated_list_inner with trailing separator enabled.
    fn parse_separated_list<
        Element: TypedSyntaxNode<'a>,
        Separator: syntax::node::Terminal<'a>,
        ElementOrSeparatorGreen,
    >(
        &mut self,
        try_parse_list_element: fn(&mut Self) -> TryParseResult<Element::Green>,
        should_stop: fn(SyntaxKind) -> bool,
        expected_element: &'static str,
    ) -> Vec<ElementOrSeparatorGreen>
    where
        ElementOrSeparatorGreen: From<Separator::Green> + From<Element::Green>,
    {
        self.parse_separated_list_inner::<Element, Separator, ElementOrSeparatorGreen>(
            try_parse_list_element,
            should_stop,
            expected_element,
            None,
        )
    }

    /// Peeks at the next terminal from the Lexer without taking it.
    pub fn peek(&self) -> &LexerTerminal<'a> {
        self.next_terminal()
    }

    /// Peeks at the token following the next one.
    /// Assumption: the next token is not EOF.
    pub fn peek_next_next_kind(&mut self) -> SyntaxKind {
        self.next_next_terminal().kind
    }

    /// Consumes a '&&' token and pushes two '&' tokens into the token stream.
    /// If the current token is not '&&', does nothing.
    fn unglue_andand_for_unary(&mut self) {
        self.unglue::<TerminalAndAnd<'_>, TerminalAnd<'_>, TerminalAnd<'_>>("&", "&");
    }

    /// Consumes a `Original` token and replaces it instead with its split into `First` and `Second`
    /// tokens and pushes them into the token stream. If the current token is not 'Original',
    /// does nothing.
    fn unglue<
        Original: syntax::node::Terminal<'a>,
        First: syntax::node::Terminal<'a>,
        Second: syntax::node::Terminal<'a>,
    >(
        &mut self,
        first: &'static str,
        second: &'static str,
    ) {
        if self.peek().kind != Original::KIND {
            return;
        }
        // Consume the original token and grab its trivia.
        let orig = self.advance();
        // Pushing the second first, with the trailing trivia.
        self.terminals.push_front(LexerTerminal {
            text: SmolStrId::from(self.db, second),
            kind: Second::KIND,
            leading_trivia: vec![],
            trailing_trivia: orig.trailing_trivia,
        });
        // Pushing the first second, with the leading trivia.
        self.terminals.push_front(LexerTerminal {
            text: SmolStrId::from(self.db, first),
            kind: First::KIND,
            leading_trivia: orig.leading_trivia,
            trailing_trivia: vec![],
        });
    }

    /// Move forward one terminal.
    fn take_raw(&mut self) -> LexerTerminal<'a> {
        self.offset = self.offset.add_width(self.current_width);
        self.current_width = self.next_terminal().width(self.db);
        self.last_trivia_length =
            trivia_total_width(self.db, &self.next_terminal().trailing_trivia);
        self.advance()
    }

    /// Skips the next, non-taken, token. A skipped token is a token which is not expected where it
    /// is found. Skipping this token means reporting an error, appending the token to the
    /// current trivia as skipped, and continuing the compilation as if it wasn't there.
    fn skip_token(&mut self, diagnostic_kind: ParserDiagnosticKind) {
        if self.peek().kind == SyntaxKind::TerminalEndOfFile {
            self.add_diagnostic(diagnostic_kind, TextSpan::cursor(self.offset));
            return;
        }
        let terminal = self.take_raw();
        self.append_skipped_token_to_pending_trivia(terminal, diagnostic_kind);
    }

    /// Appends the given terminal to the pending trivia and reports a diagnostic. Used for skipping
    /// a taken ('take_raw') token.
    fn append_skipped_token_to_pending_trivia(
        &mut self,
        terminal: LexerTerminal<'a>,
        diagnostic_kind: ParserDiagnosticKind,
    ) {
        let orig_offset = self.offset;
        let diag_start =
            self.offset.add_width(trivia_total_width(self.db, &terminal.leading_trivia));
        let diag_end = diag_start.add_width(TextWidth::from_str(terminal.text.long(self.db)));

        // Add to pending trivia.
        self.pending_trivia.extend(terminal.leading_trivia);
        self.pending_trivia.push(TokenSkipped::new_green(self.db, terminal.text).into());
        let trailing_trivia_width = trivia_total_width(self.db, &terminal.trailing_trivia);
        self.pending_trivia.extend(terminal.trailing_trivia);
        self.pending_skipped_token_diagnostics.push(PendingParserDiagnostic {
            kind: diagnostic_kind,
            span: TextSpan::new(diag_start, diag_end),
            leading_trivia_start: orig_offset,
            trailing_trivia_end: diag_end.add_width(trailing_trivia_width),
        });
    }

    /// A wrapper for `skip_taken_node_with_offset` to report the skipped node diagnostic relative
    /// to the current offset. Use this when the skipped node is the last node taken.
    fn skip_taken_node_from_current_offset(
        &mut self,
        node_to_skip: impl Into<SkippedNodeGreen<'a>>,
        diagnostic_kind: ParserDiagnosticKind,
    ) {
        self.skip_taken_node_with_offset(
            node_to_skip,
            diagnostic_kind,
            self.offset.add_width(self.current_width),
        )
    }

    /// Skips the given node which is a variant of `SkippedNode` and is already taken. A skipped
    /// node is a node which is not expected where it is found. Skipping this node means
    /// reporting the given error (pointing to right after the node), appending the node to the
    /// current trivia as skipped, and continuing the compilation as if it wasn't there.
    /// `end_of_node_offset` is the offset of the end of the skipped node.
    fn skip_taken_node_with_offset(
        &mut self,
        node_to_skip: impl Into<SkippedNodeGreen<'a>>,
        diagnostic_kind: ParserDiagnosticKind,
        end_of_node_offset: TextOffset,
    ) {
        let trivium_green = TriviumSkippedNode::new_green(self.db, node_to_skip.into()).into();

        // Add to pending trivia.
        self.pending_trivia.push(trivium_green);

        let start_of_node_offset = end_of_node_offset.sub_width(trivium_green.0.width(self.db));
        let diag_pos = end_of_node_offset
            .sub_width(trailing_trivia_width(self.db, trivium_green.0).unwrap_or_default());

        self.pending_skipped_token_diagnostics.push(PendingParserDiagnostic {
            kind: diagnostic_kind,
            span: TextSpan::cursor(diag_pos),
            leading_trivia_start: start_of_node_offset,
            trailing_trivia_end: end_of_node_offset,
        });
    }

    /// Skips the current token, reports the given diagnostic and returns missing kind of the
    /// expected terminal.
    fn skip_token_and_return_missing<ExpectedTerminal: syntax::node::Terminal<'a>>(
        &mut self,
        diagnostic: ParserDiagnosticKind,
    ) -> ExpectedTerminal::Green {
        self.skip_token(diagnostic);
        ExpectedTerminal::missing(self.db)
    }

    /// Skips a given SkippedNode, reports the given diagnostic (pointing to right after the node)
    /// and returns missing kind of the expected node.
    fn skip_taken_node_and_return_missing<ExpectedNode: TypedSyntaxNode<'a>>(
        &mut self,
        node_to_skip: impl Into<SkippedNodeGreen<'a>>,
        diagnostic_kind: ParserDiagnosticKind,
    ) -> ExpectedNode::Green {
        self.skip_taken_node_from_current_offset(node_to_skip, diagnostic_kind);
        ExpectedNode::missing(self.db)
    }

    /// Skips terminals until `should_stop` returns `true`.
    ///
    /// Returns the span of the skipped terminals, if any.
    pub(crate) fn skip_until(
        &mut self,
        should_stop: fn(SyntaxKind) -> bool,
    ) -> Result<(), SkippedError> {
        let mut diag_start = None;
        let mut diag_end = None;
        while !should_stop(self.peek().kind) {
            let terminal = self.take_raw();
            diag_start.get_or_insert(self.offset);
            diag_end =
                Some(self.offset.add_width(TextWidth::from_str(terminal.text.long(self.db))));

            self.pending_trivia.extend(terminal.leading_trivia);
            self.pending_trivia.push(TokenSkipped::new_green(self.db, terminal.text).into());
            self.pending_trivia.extend(terminal.trailing_trivia);
        }
        if let (Some(diag_start), Some(diag_end)) = (diag_start, diag_end) {
            Err(SkippedError(TextSpan::new(diag_start, diag_end)))
        } else {
            Ok(())
        }
    }

    /// Builds a new terminal to replace the given terminal by gluing the recently skipped terminals
    /// to the given terminal as extra leading trivia.
    fn add_trivia_to_terminal<Terminal: syntax::node::Terminal<'a>>(
        &mut self,
        lexer_terminal: LexerTerminal<'a>,
    ) -> Terminal::Green {
        let LexerTerminal { text, kind: _, leading_trivia, trailing_trivia } = lexer_terminal;
        let token = Terminal::TokenType::new_green(self.db, text);
        let mut new_leading_trivia = mem::take(&mut self.pending_trivia);

        self.consume_pending_skipped_diagnostics();

        new_leading_trivia.extend(leading_trivia);
        Terminal::new_green(
            self.db,
            Trivia::new_green(self.db, &new_leading_trivia),
            token,
            Trivia::new_green(self.db, &trailing_trivia),
        )
    }

    /// Adds the pending skipped-tokens diagnostics, merging consecutive similar ones, and reset
    /// self.pending_skipped_token_diagnostics.
    fn consume_pending_skipped_diagnostics(&mut self) {
        let mut pending_skipped = self.pending_skipped_token_diagnostics.drain(..);
        let Some(first) = pending_skipped.next() else {
            return;
        };

        let mut current_diag = first;

        for diag in pending_skipped {
            if diag.kind == current_diag.kind
                && current_diag.trailing_trivia_end == diag.leading_trivia_start
            {
                // Aggregate this diagnostic with the previous ones.
                current_diag = PendingParserDiagnostic {
                    span: TextSpan::new(current_diag.span.start, diag.span.end),
                    kind: diag.kind,
                    leading_trivia_start: current_diag.leading_trivia_start,
                    trailing_trivia_end: diag.trailing_trivia_end,
                };
            } else {
                // Produce a diagnostic from the aggregated ones, and start aggregating a new
                // diagnostic.
                self.diagnostics.add(ParserDiagnostic {
                    file_id: self.file_id,
                    span: current_diag.span,
                    kind: current_diag.kind,
                });
                current_diag = diag;
            }
        }
        // Produce a diagnostic from the aggregated ones at the end.
        self.add_diagnostic(current_diag.kind, current_diag.span);
    }

    /// Takes a token from the Lexer and place it in self.current. If tokens were skipped, glue them
    /// to this token as leading trivia.
    pub fn take<Terminal: syntax::node::Terminal<'a>>(&mut self) -> Terminal::Green {
        let token = self.take_raw();
        assert_eq!(token.kind, Terminal::KIND);
        self.add_trivia_to_terminal::<Terminal>(token)
    }

    /// If the current leading trivia start with non-doc comments, creates a new `ItemHeaderDoc` and
    /// appends the trivia to it. The purpose of this item is to prevent non-doc comments moving
    /// from the top of the file formatter.
    fn take_doc(&mut self) -> Option<ItemHeaderDocGreen<'a>> {
        // Take all the trivia from `self.next_terminal`, until a doc-comment is found. If the
        // result does not contain a non-doc comment (i.e. regular comment or inner
        // comment), return None and do not change the next terminal leading trivia.
        let mut has_header_doc = false;
        let mut split_index = 0;
        for trivium in &self.next_terminal().leading_trivia {
            match trivium.0.long(self.db).kind {
                SyntaxKind::TokenSingleLineComment | SyntaxKind::TokenSingleLineInnerComment => {
                    has_header_doc = true;
                }
                SyntaxKind::TokenSingleLineDocComment => {
                    break;
                }
                _ => {}
            }
            split_index += 1;
        }
        if !has_header_doc {
            return None;
        }
        // Split the trivia into header doc and the rest.
        let header_doc = {
            let next_mut = self.next_terminal_mut();
            let leading_trivia = next_mut.leading_trivia.split_off(split_index);
            std::mem::replace(&mut next_mut.leading_trivia, leading_trivia)
        };
        let empty_text_id = SmolStrId::from(self.db, "");
        let empty_lexer_terminal = LexerTerminal {
            text: empty_text_id,
            kind: SyntaxKind::TerminalEmpty,
            leading_trivia: header_doc,
            trailing_trivia: vec![],
        };
        self.offset = self.offset.add_width(empty_lexer_terminal.width(self.db));

        let empty_terminal = self.add_trivia_to_terminal::<TerminalEmpty<'_>>(empty_lexer_terminal);
        Some(ItemHeaderDoc::new_green(self.db, empty_terminal))
    }

    /// If the current terminal is of kind `Terminal`, returns its Green wrapper. Otherwise, returns
    /// TryParseFailure.
    /// Note that this function should not be called for 'TerminalIdentifier' -
    /// try_parse_identifier() should be used instead.
    fn try_parse_token<Terminal: syntax::node::Terminal<'a>>(
        &mut self,
    ) -> TryParseResult<Terminal::Green> {
        if Terminal::KIND == self.peek().kind {
            Ok(self.take::<Terminal>())
        } else {
            Err(TryParseFailure::SkipToken)
        }
    }

    /// If the current token is of kind `token_kind`, returns a GreenId of a node with this kind.
    /// Otherwise, returns Token::Missing.
    ///
    /// Note that this function should not be called for 'TerminalIdentifier' - parse_identifier()
    /// should be used instead.
    fn parse_token<Terminal: syntax::node::Terminal<'a>>(&mut self) -> Terminal::Green {
        self.parse_token_ex::<Terminal>(true)
    }

    /// Same as [Self::parse_token], except that the diagnostic may be omitted.
    fn parse_token_ex<Terminal: syntax::node::Terminal<'a>>(
        &mut self,
        report_diagnostic: bool,
    ) -> Terminal::Green {
        match self.try_parse_token::<Terminal>() {
            Ok(green) => green,
            Err(_) => {
                if report_diagnostic {
                    self.create_and_report_missing_terminal::<Terminal>()
                } else {
                    Terminal::missing(self.db)
                }
            }
        }
    }
}

/// Controls whether Lbrace (`{`) is allowed in the expression.
///
/// Lbrace is always allowed in sub-expressions (e.g. in parenthesized expression). For example,
/// while `1 + MyStruct { ... }` may not be valid, `1 + (MyStruct { ... })` is always ok.
///
/// This can be used to parse the argument of a `match` statement,
/// so that the `{` that opens the `match` body is not confused with other potential uses of
/// `{`.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum LbraceAllowed {
    Forbid,
    Allow,
}

/// Controls the behavior of the parser when encountering `&& let` tokens.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum AndLetBehavior {
    /// Parse without special handling of `&& let`.
    Simple,
    /// Stop parsing an expression at `&& let` and return the expression so far.
    Stop,
}

/// Indicates that [Parser::skip_until] skipped some terminals.
pub(crate) struct SkippedError(pub(crate) TextSpan);

/// Defines the parser behavior in the case of a parsing error.
struct ErrorRecovery {
    /// In the case of a parsing error, tokens will be skipped until `should_stop`
    /// returns `true`. For example, one can stop at tokens such as `,` and `}`.
    should_stop: fn(SyntaxKind) -> bool,
}

enum ExternItem<'a> {
    Function(ItemExternFunctionGreen<'a>),
    Type(ItemExternTypeGreen<'a>),
}

#[derive(Debug)]
enum ImplItemOrAlias<'a> {
    Item(ItemImplGreen<'a>),
    Alias(ItemImplAliasGreen<'a>),
}

/// A parser diagnostic that is not yet reported as it is accumulated with similar consecutive
/// diagnostics.
pub struct PendingParserDiagnostic {
    pub span: TextSpan,
    pub kind: ParserDiagnosticKind,
    pub leading_trivia_start: TextOffset,
    pub trailing_trivia_end: TextOffset,
}

/// Returns the total width of the given trivia list.
fn trivia_total_width(db: &dyn Database, trivia: &[TriviumGreen<'_>]) -> TextWidth {
    trivia.iter().map(|trivium| trivium.0.width(db)).sum::<TextWidth>()
}

/// The width of the trailing trivia, traversing the tree to the bottom right node.
fn trailing_trivia_width(db: &dyn Database, green_id: GreenId<'_>) -> Option<TextWidth> {
    let node = green_id.long(db);
    if node.kind == SyntaxKind::Trivia {
        return Some(node.width(db));
    }
    match &node.details {
        GreenNodeDetails::Token(_) => Some(TextWidth::default()),
        GreenNodeDetails::Node { children, .. } => {
            for child in children.iter().rev() {
                if let Some(width) = trailing_trivia_width(db, *child) {
                    return Some(width);
                }
            }
            None
        }
    }
}
